From 5c8949cf8b6d991073f096641404ddff074b67ac Mon Sep 17 00:00:00 2001 From: Julian Daube Date: Sun, 25 Sep 2016 17:05:25 +0200 Subject: [PATCH] add main file --- executer.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 executer.go diff --git a/executer.go b/executer.go new file mode 100644 index 0000000..8bd583e --- /dev/null +++ b/executer.go @@ -0,0 +1,69 @@ +package executer + +import ( + "errors" + "os/exec" + "time" +) + +var ErrTimeout = errors.New("operation timed out") + +type Job struct { + Cmd *exec.Cmd + Err chan error +} + +type Worker struct { + Jobs chan Job + Timeout time.Duration +} + +func NewJob(e *exec.Cmd) Job { + return Job{ + Cmd: e, + Err: make(chan error), + } +} + +func NewWorker(timeout time.Duration) *Worker { + w := &Worker{ + Jobs: make(chan Job, 1), + Timeout: timeout, + } + // start worker routine + go w.run() + return w +} + +// runs in own goroutine +func (e *Worker) run() { + var done chan error + + if e.Timeout != 0 { + done = make(chan error) + defer close(done) + } + + for j := range e.Jobs { + if e.Timeout == 0 { + // run synchronously + j.Err <- j.Cmd.Run() + } else { + // run asyncly and timeout + go func() { + done <- j.Cmd.Run() + }() + + select { + case err := <-done: + j.Err <- err + case <-time.After(e.Timeout): + j.Err <- j.Cmd.Process.Kill() + j.Err <- ErrTimeout + } + } + + // signal done + close(j.Err) + } +}