From 09d8b700096b35f2e5a3a8b1b7e4a782fdb49038 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 24 Sep 2025 18:58:46 +0300 Subject: [PATCH] Store service process ID in struct --- src/ectl/main.go | 10 +++++++- src/esvm/main.go | 4 ++-- src/esvm/service.go | 56 +++++++++++++-------------------------------- src/esvm/socket.go | 2 ++ 4 files changed, 29 insertions(+), 43 deletions(-) diff --git a/src/ectl/main.go b/src/ectl/main.go index 6e38459..3ce530e 100644 --- a/src/ectl/main.go +++ b/src/ectl/main.go @@ -255,6 +255,7 @@ func main() { serviceState := returnedJsonData["state"].(string) serviceEnabled := returnedJsonData["is_enabled"].(bool) serviceStage := int(returnedJsonData["stage"].(float64)) + processID := int(returnedJsonData["process_id"].(float64)) fmt.Printf("Name: %s\n", flag.Arg(2)) fmt.Printf("State: %s\n", serviceState) @@ -263,6 +264,9 @@ func main() { } else { fmt.Printf("Enabled: %t\n", serviceEnabled) } + if serviceState == "running" { + fmt.Printf("Process ID: %d\n", processID) + } return } else if flag.Arg(1) == "list" { @@ -317,7 +321,8 @@ func main() { serviceName := serviceMap.(map[string]any)["name"].(string) serviceState := serviceMap.(map[string]any)["state"].(string) serviceEnabled := serviceMap.(map[string]any)["is_enabled"].(bool) - serviceStage := serviceMap.(map[string]any)["stage"].(int) + serviceStage := int(serviceMap.(map[string]any)["stage"].(float64)) + processID := int(serviceMap.(map[string]any)["process_id"].(float64)) fmt.Printf("Name: %s\n", serviceName) fmt.Printf("State: %s\n", serviceState) @@ -326,6 +331,9 @@ func main() { } else { fmt.Printf("Enabled: %t\n", serviceEnabled) } + if serviceState == "running" { + fmt.Printf("Process ID: %d\n", processID) + } fmt.Println() } diff --git a/src/esvm/main.go b/src/esvm/main.go index 2ba5f02..be25c80 100644 --- a/src/esvm/main.go +++ b/src/esvm/main.go @@ -199,7 +199,7 @@ func Init() { logger.Fatalf("Error: could not initialize ESVM: %s", err) } - Services = append(Services, service) + Services = append(Services, &service) logger.Printf("Service (%s) has been initialized!\n", service.Name) } @@ -261,7 +261,7 @@ func Destroy() { func GetServiceByName(name string) *EnitService { for _, service := range Services { if service.Name == name { - return &service + return service } } return nil diff --git a/src/esvm/service.go b/src/esvm/service.go index 8aab307..9bf3f15 100644 --- a/src/esvm/service.go +++ b/src/esvm/service.go @@ -46,11 +46,12 @@ type EnitService struct { Restart string `yaml:"restart,omitempty"` LogOutput bool `yaml:"log_output,omitempty"` ServiceRunPath string + processID int restartCount int stopChannel chan bool } -var Services = make([]EnitService, 0) +var Services = make([]*EnitService, 0) var EnabledServices = make(map[int][]string) var startedServicesOrder = make([]string, 0) @@ -74,31 +75,11 @@ func (service *EnitService) GetUnmetDependencies() (missingDependencies []string } func (service *EnitService) GetProcess() *os.Process { - bytes, err := os.ReadFile(path.Join(service.ServiceRunPath, "process")) - if err != nil { - return nil - } - - pid, err := strconv.Atoi(strings.TrimSpace(string(bytes))) - if err != nil { - return nil - } - - process, err := os.FindProcess(pid) - if err != nil { - return nil - } + process, _ := os.FindProcess(service.processID) return process } -func (service *EnitService) setProcessID(pid int) error { - if err := os.WriteFile(path.Join(service.ServiceRunPath, "process"), []byte(strconv.Itoa(pid)), 0644); err != nil { - return err - } - return nil -} - func (service *EnitService) GetCurrentState() EnitServiceState { bytes, err := os.ReadFile(path.Join(service.ServiceRunPath, "state")) if err != nil { @@ -187,17 +168,9 @@ func (service *EnitService) StartService() error { return err } - err := service.setProcessID(cmd.Process.Pid) - if err != nil { - // Close log file if not nil - if logFile != nil { - logFile.Close() - } + service.processID = cmd.Process.Pid - return err - } - - err = service.setCurrentState(EnitServiceRunning) + err := service.setCurrentState(EnitServiceRunning) if err != nil { // Close log file if not nil if logFile != nil { @@ -243,6 +216,8 @@ func (service *EnitService) StartService() error { _ = service.StartService() } } + + service.processID = 0 }() // Add to started services order slice @@ -263,12 +238,13 @@ func (service *EnitService) StopService() error { logger.Printf("Stopping service (%s)...", service.Name) newServiceStatus := EnitServiceCrashed - defer service.setCurrentState(newServiceStatus) - defer service.setProcessID(0) + defer func() { + service.setCurrentState(newServiceStatus) + service.processID = 0 + }() if service.ExitMethod == "kill" { - process := service.GetProcess() - if err := process.Signal(syscall.Signal(0)); err != nil { + if err := service.GetProcess().Signal(syscall.Signal(0)); err != nil { newServiceStatus = EnitServiceStopped logger.Printf("Service (%s) has stopped (Process already dead)", service.Name) return nil @@ -277,8 +253,8 @@ func (service *EnitService) StopService() error { go func() { service.stopChannel <- true }() // Send SIGTERM signal to process - if err := process.Signal(syscall.SIGTERM); err != nil { - process.Signal(syscall.SIGKILL) + if err := service.GetProcess().Signal(syscall.SIGTERM); err != nil { + service.GetProcess().Signal(syscall.SIGKILL) return fmt.Errorf("could not stop process gracefully") } @@ -286,7 +262,7 @@ func (service *EnitService) StopService() error { exited := make(chan bool) go func() { for { - if err := process.Signal(syscall.Signal(0)); err != nil { + if err := service.GetProcess().Signal(syscall.Signal(0)); err != nil { break } } @@ -296,7 +272,7 @@ func (service *EnitService) StopService() error { select { case <-exited: case <-time.After(5 * time.Second): - process.Signal(syscall.SIGKILL) + service.GetProcess().Signal(syscall.SIGKILL) return fmt.Errorf("could not stop process gracefully") } } else { diff --git a/src/esvm/socket.go b/src/esvm/socket.go index a9854ed..55d88cd 100644 --- a/src/esvm/socket.go +++ b/src/esvm/socket.go @@ -223,6 +223,7 @@ func handleStatusServiceCommand(conn net.Conn, jsonData map[string]any) { statusMap := make(map[string]any) statusMap["name"] = service.Name statusMap["state"] = EnitServiceStateNames[service.GetCurrentState()] + statusMap["process_id"] = service.processID statusMap["is_enabled"], statusMap["stage"] = service.isEnabled() // Encode map to json string @@ -244,6 +245,7 @@ func handleListServicesCommand(conn net.Conn, _ map[string]any) { statusMap := make(map[string]any) statusMap["name"] = service.Name statusMap["state"] = EnitServiceStateNames[service.GetCurrentState()] + statusMap["process_id"] = service.processID statusMap["is_enabled"], statusMap["stage"] = service.isEnabled() servicesMap["services"] = append(servicesMap["services"].([]map[string]any), statusMap) }