Launch
This commit is contained in:
91
internal/engine/process.go
Normal file
91
internal/engine/process.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"socksrevivepc/internal/oscmd"
|
||||
)
|
||||
|
||||
type ManagedProcess struct {
|
||||
cmd *exec.Cmd
|
||||
name string
|
||||
logger *Logger
|
||||
mu sync.Mutex
|
||||
done chan error
|
||||
}
|
||||
|
||||
func StartProcess(ctx context.Context, root, name, exe string, args []string, logger *Logger) (*ManagedProcess, error) {
|
||||
if strings.TrimSpace(exe) == "" {
|
||||
return nil, errors.New(name + " executable path is empty")
|
||||
}
|
||||
if !filepath.IsAbs(exe) {
|
||||
exe = filepath.Join(root, exe)
|
||||
}
|
||||
cmd := oscmd.CommandContext(ctx, exe, args...)
|
||||
cmd.Dir = root
|
||||
stdout, _ := cmd.StdoutPipe()
|
||||
stderr, _ := cmd.StderrPipe()
|
||||
p := &ManagedProcess{cmd: cmd, name: name, logger: logger, done: make(chan error, 1)}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Add("info", "%s started: %s %s", name, exe, strings.Join(args, " "))
|
||||
go p.pipe(stdout, "info")
|
||||
go p.pipe(stderr, "warn")
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
p.done <- err
|
||||
if err != nil {
|
||||
logger.Add("warn", "%s stopped: %v", name, err)
|
||||
} else {
|
||||
logger.Add("info", "%s stopped", name)
|
||||
}
|
||||
}()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *ManagedProcess) Exited() (bool, error) {
|
||||
if p == nil || p.done == nil {
|
||||
return true, nil
|
||||
}
|
||||
select {
|
||||
case err := <-p.done:
|
||||
return true, err
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ManagedProcess) pipe(r io.Reader, level string) {
|
||||
s := bufio.NewScanner(r)
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line != "" {
|
||||
p.logger.Add(level, "%s: %s", p.name, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ManagedProcess) Stop() {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if p == nil || p.cmd == nil || p.cmd.Process == nil {
|
||||
return
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
_ = p.cmd.Process.Kill()
|
||||
} else {
|
||||
_ = p.cmd.Process.Signal(ioSignalInterrupt())
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
_ = p.cmd.Process.Kill()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user