From 2461481468905cde4187eba7a245df9e026b3848 Mon Sep 17 00:00:00 2001 From: Graham Clark Date: Sun, 18 Apr 2021 18:41:05 -0400 Subject: [PATCH] Attempt to fix sporadic ctrl-c bug Issue #120 reports that if you hit ctrl-c shortly after startup, occasionally termshark will not quit correctly, and subsequent ctrl-c invocations make no difference. This occurs only if reading from an interface. In that case, the PSML-reading process starts with stdin set to the read-end of a pipe. That pipe is supplied with pcap data via a tail command, reading from the gradually accumulating pcap on disk. The goroutine that tracks changes to PSML process state needs to ensure that if the controlling context is cancelled, this pipe is closed. Failing to do this can lead to Go's cmd.Exec never responding to Wait() because internally, the Wait() calls itself waits for a private goroutine - that goroutine is running io.Copy() from the user's process IO reader (our pipe) to the real process's stdin. Closing the pipe will cause io.Copy() to terminate, then cmd.Exec's private goroutine to terminate, and so allows Wait() to return a value. --- pcap/loader.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pcap/loader.go b/pcap/loader.go index bfc23fe3..95746dfe 100644 --- a/pcap/loader.go +++ b/pcap/loader.go @@ -1359,6 +1359,15 @@ func (p *PsmlLoader) loadPsmlSync(iloader *InterfaceLoader, e iPsmlLoaderEnv, cb //====================================================================== + closedPipe := false + closePipe := func() { + if !closedPipe { + fifoPipeWriter.Close() + fifoPipeReader.Close() + closedPipe = true + } + } + if p.ReadingFromFifo() { // PcapPsml will be nil if here @@ -1378,8 +1387,7 @@ func (p *PsmlLoader) loadPsmlSync(iloader *InterfaceLoader, e iPsmlLoaderEnv, cb // is used as stdin for the psml command, which also runs in this // goroutine. defer func() { - fifoPipeWriter.Close() - fifoPipeReader.Close() + closePipe() }() // wrap the read end of the pipe with a Read() function that counts @@ -1425,6 +1433,10 @@ func (p *PsmlLoader) loadPsmlSync(iloader *InterfaceLoader, e iPsmlLoaderEnv, cb if err != nil { log.Infof("Did not kill tshark psml process: %v", err) } + + if p.ReadingFromFifo() { + closePipe() + } } loop: