github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/wordsmith/utility/command.go (about) 1 // Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved. 2 // 3 // This software (Documize Community Edition) is licensed under 4 // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html 5 // 6 // You can operate outside the AGPL restrictions by purchasing 7 // Documize Enterprise Edition and obtaining a commercial license 8 // by contacting <sales@documize.com>. 9 // 10 // https://documize.com 11 12 package utility 13 14 import ( 15 "bytes" 16 "github.com/documize/community/wordsmith/log" 17 "errors" 18 "os/exec" 19 "time" 20 ) 21 22 var errTimeout = errors.New("conversion timelimit exceeded") 23 24 // CommandWithTimeout runs a command but stops it if it does not finish within the timout above. 25 func CommandWithTimeout(command *exec.Cmd, timeout time.Duration) ([]byte, error) { 26 var output bytes.Buffer 27 //fmt.Println("DEBUG CommandWithTimeout: %v", command.Args) 28 command.Stdout = &output 29 command.Stderr = &output 30 if err := command.Start(); err != nil { 31 return nil, err 32 } 33 done := make(chan error, 1) 34 defer close(done) 35 go func() { 36 done <- command.Wait() 37 }() 38 select { 39 case <-time.After(timeout): 40 if err := command.Process.Kill(); err != nil { 41 log.Error("failed to kill: ", err) 42 } 43 <-done // prevent memory leak 44 //fmt.Println("DEBUG timeout") 45 return nil, errTimeout 46 case err := <-done: 47 if err != nil { 48 //fmt.Println("DEBUG error return") 49 return output.Bytes(), err 50 } 51 if !command.ProcessState.Success() { 52 err = errors.New(string(output.Bytes())) 53 //fmt.Println("DEBUG not successful") 54 return nil, err 55 } 56 //fmt.Println("DEBUG successful return") 57 return output.Bytes(), nil 58 } 59 }