github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/cmd/state-svc/internal/rtwatcher/entry.go (about)

     1  package rtwatcher
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/ActiveState/cli/internal/analytics/dimensions"
     7  	"github.com/ActiveState/cli/internal/errs"
     8  	"github.com/ActiveState/cli/internal/fileutils"
     9  	"github.com/ActiveState/cli/internal/logging"
    10  	"github.com/shirou/gopsutil/v3/process"
    11  )
    12  
    13  type entry struct {
    14  	PID    int                `json:"pid"`
    15  	Exec   string             `json:"exec"`
    16  	Source string             `json:"source"`
    17  	Dims   *dimensions.Values `json:"dims"`
    18  }
    19  
    20  // processError wraps an OS-level error, not a State Tool error.
    21  type processError struct {
    22  	*errs.WrapperError
    23  }
    24  
    25  func (e entry) IsRunning() (bool, error) {
    26  	logging.Debug("Checking if %s (%d) is still running", e.Exec, e.PID)
    27  
    28  	proc, err := process.NewProcess(int32(e.PID))
    29  	if err != nil {
    30  		if errors.Is(err, process.ErrorProcessNotRunning) {
    31  			logging.Debug("Process %d is no longer running, recieved error: %s", e.PID, err.Error())
    32  			return false, nil
    33  		}
    34  		return false, errs.Wrap(err, "Could not find process: %d", e.PID)
    35  	}
    36  
    37  	exe, err := proc.Exe()
    38  	if err != nil {
    39  		return false, &processError{errs.Wrap(err, "Could not get executable of process: %d", e.PID)}
    40  	}
    41  
    42  	match, err := fileutils.PathsMatch(exe, e.Exec)
    43  	if err != nil {
    44  		return false, errs.Wrap(err, "Could not compare paths: %s, %s", exe, e.Exec)
    45  	}
    46  	if match {
    47  		logging.Debug("Process %d matched", e.PID)
    48  		return true, nil
    49  	}
    50  
    51  	logging.Debug("Process %d not matched, expected %s to match %s", e.PID, exe, e.Exec)
    52  	return false, nil
    53  }