correct stdin handling. stderr might still be broken

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2019-05-10 01:54:36 +00:00
parent 8a5c9922e4
commit 954470c34c
4 changed files with 82 additions and 44 deletions

3
example1/Makefile Normal file
View File

@ -0,0 +1,3 @@
all:
go build
./example1

BIN
example1/example1 Executable file

Binary file not shown.

27
example1/main.go Normal file
View File

@ -0,0 +1,27 @@
package main
/*
import "log"
import "reflect"
import "os"
*/
// import "github.com/davecgh/go-spew/spew"
import "git.wit.com/jcarr/shell"
func main() {
shell.SpewOn()
shell.Run("ls /tmp")
shell.Run("ping -c 4 localhost")
// slow down the polling to every 2 seconds
shell.SetDelayInMsec(2000)
shell.Run("ping -c 4 localhost")
// TODO: this might not be working
// check error handling
shell.Run("ls /tmpthisisnothere")
}

View File

@ -16,6 +16,7 @@ var shellStdout *os.File
var shellStderr *os.File var shellStderr *os.File
var spewOn bool = false var spewOn bool = false
var msecDelay int = 20 // number of milliseconds to delay between reads with no data
func Script(cmds string) int { func Script(cmds string) int {
// split on new lines (while we are at it, handle stupid windows text files // split on new lines (while we are at it, handle stupid windows text files
@ -40,6 +41,10 @@ func SpewOn() {
spewOn = true spewOn = true
} }
func SetDelayInMsec(msecs int) {
msecDelay = msecs
}
func SetStdout(newout *os.File) { func SetStdout(newout *os.File) {
shellStdout = newout shellStdout = newout
} }
@ -85,74 +90,45 @@ func Run(cmdline string) int {
newreader := bufio.NewReader(pstdout) newreader := bufio.NewReader(pstdout)
nbr := nbreader.NewNBReader(newreader, 1024) nbr := nbreader.NewNBReader(newreader, 1024)
newerrreader := bufio.NewReader(pstderr) // nbrerr := nbreader.NewNBReader(newerrreader, 1024)
nbrerr := nbreader.NewNBReader(newerrreader, 1024)
tmp := bufio.NewReader(pstderr)
go NonBlockingReader(tmp, shellStderr)
totalCount := 0 totalCount := 0
for { var dead bool = false
time.Sleep(2 * time.Millisecond) // only check the buffer 500 times a second for (dead == false) {
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // only check the buffer 500 times a second
// log.Println("sleep done") // log.Println("sleep done")
var empty bool = false
// tight loop that reads 1K at a time until buffer is empty // tight loop that reads 1K at a time until buffer is empty
for { for (empty == false) {
oneByte := make([]byte, 1024) oneByte := make([]byte, 1024)
count, err := nbr.Read(oneByte) count, err := nbr.Read(oneByte)
totalCount += count totalCount += count
if (err != nil) { if (err != nil) {
// log.Println("Read() count = ", count, "err = ", err) log.Println("Read() count = ", count, "err = ", err)
oneByte = make([]byte, 1024) oneByte = make([]byte, 1024)
count, err = nbr.Read(oneByte) count, err = nbr.Read(oneByte)
f.Write([]byte(string(oneByte))) f.Write([]byte(string(oneByte)))
f.Flush() f.Flush()
empty = true
dead = true
} }
f.Write([]byte(string(oneByte))) f.Write([]byte(string(oneByte)))
f.Flush() f.Flush()
if (count == 0) { if (count == 0) {
break empty = true
} }
} }
if (totalCount != 0) { if (totalCount != 0) {
log.Println("totalCount = ", totalCount) log.Println("STDOUT: totalCount = ", totalCount)
totalCount = 0
} }
//
// HANDLE STDERR
// HANDLE STDERR
//
oneByte := make([]byte, 1024)
count, err := nbrerr.Read(oneByte)
if (err != nil) {
oneByte = make([]byte, 1024)
count, err = nbrerr.Read(oneByte)
f.Write([]byte(string(oneByte)))
f.Flush()
log.Println("Read() count = ", count, "err = ", err)
// spew.Dump(process.Process)
// spew.Dump(process.ProcessState)
err := process.Wait()
if err != nil {
if (spewOn) {
spew.Dump(err.(*exec.ExitError))
spew.Dump(process.ProcessState)
}
stuff := err.(*exec.ExitError)
log.Println("ERROR ", stuff)
log.Println("END ", cmdline)
return -1
}
log.Println("END ", cmdline)
return 0
} else {
f.Write([]byte(string(oneByte)))
f.Flush()
}
// spew.Dump(reflect.ValueOf(cmd.Process).Elem())
} }
err := process.Wait() err := process.Wait()
@ -177,3 +153,35 @@ func Daemon(cmdline string, timeout time.Duration) int {
time.Sleep(timeout) time.Sleep(timeout)
} }
} }
// pass in two file handles (1 read, 1 write)
func NonBlockingReader(buffReader *bufio.Reader, writeFileHandle *os.File) {
// newreader := bufio.NewReader(readFileHandle)
// create a nonblocking GO reader
nbr := nbreader.NewNBReader(buffReader, 1024)
for {
// defer buffReader.Close()
// defer writeFileHandle.Flush()
defer writeFileHandle.Close()
totalCount := 0
for {
oneByte := make([]byte, 1024)
count, err := nbr.Read(oneByte)
if (err != nil) {
log.Println("count, err =", count, err)
return
}
totalCount += count
if (count == 0) {
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // without this delay this will peg the CPU
if (totalCount != 0) {
log.Println("STDERR: totalCount = ", totalCount)
totalCount = 0
}
}
writeFileHandle.Write([]byte(string(oneByte)))
}
}
}