process: Gracefully shutdown processes
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -22,6 +23,9 @@ type Process struct {
|
|||||||
process *exec.Cmd
|
process *exec.Cmd
|
||||||
stdout io.ReadCloser
|
stdout io.ReadCloser
|
||||||
stderr io.ReadCloser
|
stderr io.ReadCloser
|
||||||
|
|
||||||
|
wg_exit *sync.WaitGroup
|
||||||
|
exit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProcess(command string) *Process {
|
func NewProcess(command string) *Process {
|
||||||
@@ -38,40 +42,57 @@ func NewProcess(command string) *Process {
|
|||||||
}
|
}
|
||||||
p.StdoutChannel = make(chan string)
|
p.StdoutChannel = make(chan string)
|
||||||
p.StderrChannel = make(chan string)
|
p.StderrChannel = make(chan string)
|
||||||
|
p.wg_exit = &sync.WaitGroup{}
|
||||||
|
p.exit = make(chan struct{})
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Process) Start() error {
|
func (p *Process) Start() error {
|
||||||
err := p.process.Start()
|
err := p.process.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Process) Observe() {
|
p.wg_exit.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
scanner := bufio.NewScanner(p.stdout)
|
scanner := bufio.NewScanner(p.stdout)
|
||||||
for scanner.Scan() {
|
for {
|
||||||
p.StdoutChannel <- scanner.Text()
|
select {
|
||||||
|
case <-p.exit:
|
||||||
|
p.wg_exit.Done()
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
for scanner.Scan() {
|
||||||
|
p.StdoutChannel <- scanner.Text()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
scanner := bufio.NewScanner(p.stderr)
|
scanner := bufio.NewScanner(p.stderr)
|
||||||
for scanner.Scan() {
|
for {
|
||||||
p.StderrChannel <- scanner.Text()
|
select {
|
||||||
|
case <-p.exit:
|
||||||
|
p.wg_exit.Done()
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
for scanner.Scan() {
|
||||||
|
p.StderrChannel <- scanner.Text()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Process) Kill() {
|
func (p Process) Stop() {
|
||||||
p.process.Process.Kill()
|
p.process.Process.Kill()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Process) Wait() error {
|
func (p *Process) Wait() error {
|
||||||
err := p.process.Wait()
|
_, err := p.process.Process.Wait()
|
||||||
if err != nil {
|
close(p.exit)
|
||||||
return err
|
p.wg_exit.Wait()
|
||||||
}
|
return err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user