X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fjob.go;h=df9151b5490883331892dcbf6a3c38ddfe97e919;hb=3c87d1cfb41e318e9349650e931b5e99cf0fc949;hp=1486706c8e3f210d1e2eb1137defc66c737050ed;hpb=d2277a376a616b98f30c46f4cc641eaebd81b53b;p=micro.git diff --git a/cmd/micro/job.go b/cmd/micro/job.go index 1486706c..df9151b5 100644 --- a/cmd/micro/job.go +++ b/cmd/micro/job.go @@ -4,15 +4,26 @@ import ( "bytes" "io" "os/exec" - "strings" ) +// Jobs are the way plugins can run processes in the background +// A job is simply a process that gets executed asynchronously +// There are callbacks for when the job exits, when the job creates stdout +// and when the job creates stderr + +// These jobs run in a separate goroutine but the lua callbacks need to be +// executed in the main thread (where the Lua VM is running) so they are +// put into the jobs channel which gets read by the main loop + +// JobFunction is a representation of a job (this data structure is what is loaded +// into the jobs channel) type JobFunction struct { function func(string, ...string) output string args []string } +// A CallbackFile is the data structure that makes it possible to catch stderr and stdout write events type CallbackFile struct { io.Writer @@ -21,17 +32,24 @@ type CallbackFile struct { } func (f *CallbackFile) Write(data []byte) (int, error) { + // This is either stderr or stdout + // In either case we create a new job function callback and put it in the jobs channel jobFunc := JobFunction{f.callback, string(data), f.args} jobs <- jobFunc return f.Writer.Write(data) } +// JobStart starts a shell command in the background with the given callbacks +// It returns an *exec.Cmd as the job id func JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string) *exec.Cmd { - split := strings.Split(cmd, " ") - args := split[1:] - cmdName := split[0] + return JobSpawn("sh", []string{"-c", cmd}, onStdout, onStderr, onExit, userargs...) +} - proc := exec.Command(cmdName, args...) +// JobSpawn starts a process with args in the background with the given callbacks +// It returns an *exec.Cmd as the job id +func JobSpawn(cmdName string, cmdArgs []string, onStdout, onStderr, onExit string, userargs ...string) *exec.Cmd { + // Set up everything correctly if the functions have been provided + proc := exec.Command(cmdName, cmdArgs...) var outbuf bytes.Buffer if onStdout != "" { proc.Stdout = &CallbackFile{&outbuf, LuaFunctionJob(onStdout), userargs} @@ -45,6 +63,7 @@ func JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string) } go func() { + // Run the process in the background and create the onExit callback proc.Run() jobFunc := JobFunction{LuaFunctionJob(onExit), string(outbuf.Bytes()), userargs} jobs <- jobFunc @@ -53,10 +72,12 @@ func JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string) return proc } +// JobStop kills a job func JobStop(cmd *exec.Cmd) { cmd.Process.Kill() } +// JobSend sends the given data into the job's stdin stream func JobSend(cmd *exec.Cmd, data string) { stdin, err := cmd.StdinPipe() if err != nil {