zfscmd: fix nil deref in waitPostLogging when command was killed

fixes #301
This commit is contained in:
Christian Schwarz 2020-04-08 00:24:37 +02:00
parent 1336c91865
commit 96e188d7c4
2 changed files with 45 additions and 3 deletions

View File

@ -1,6 +1,7 @@
package zfscmd package zfscmd
import ( import (
"os/exec"
"time" "time"
) )
@ -28,10 +29,22 @@ func waitPreLogging(c *Cmd, now time.Time) {
} }
func waitPostLogging(c *Cmd, err error, now time.Time) { func waitPostLogging(c *Cmd, err error, now time.Time) {
var total, system, user float64
total = c.Runtime().Seconds()
if ee, ok := err.(*exec.ExitError); ok {
system = ee.ProcessState.SystemTime().Seconds()
user = ee.ProcessState.UserTime().Seconds()
} else {
system = -1
user = -1
}
log := c.log(). log := c.log().
WithField("total_time_s", c.Runtime().Seconds()). WithField("total_time_s", total).
WithField("systemtime_s", c.cmd.ProcessState.SystemTime().Seconds()). WithField("systemtime_s", system).
WithField("usertime_s", c.cmd.ProcessState.UserTime().Seconds()) WithField("usertime_s", user)
if err == nil { if err == nil {
log.Info("command exited without error") log.Info("command exited without error")

View File

@ -1,7 +1,9 @@
package zfscmd package zfscmd
import ( import (
"bufio"
"bytes" "bytes"
"context"
"io" "io"
"os/exec" "os/exec"
"testing" "testing"
@ -58,3 +60,30 @@ func TestCmdStderrBehaviorStdoutPipe(t *testing.T) {
require.True(t, ok) require.True(t, ok)
require.Empty(t, ee.Stderr) // !!!!! probably not what one would expect if we only redirect stdout require.Empty(t, ee.Stderr) // !!!!! probably not what one would expect if we only redirect stdout
} }
func TestCmdProcessState(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cmd := exec.CommandContext(ctx, "bash", "-c", "echo running; sleep 3600")
stdout, err := cmd.StdoutPipe()
require.NoError(t, err)
err = cmd.Start()
require.NoError(t, err)
r := bufio.NewReader(stdout)
line, err := r.ReadString('\n')
require.NoError(t, err)
require.Equal(t, "running\n", line)
// we know it's running and sleeping
cancel()
err = cmd.Wait()
t.Logf("wait err %T\n%s", err, err)
require.Error(t, err)
ee, ok := err.(*exec.ExitError)
require.True(t, ok)
require.NotNil(t, ee.ProcessState)
require.Contains(t, ee.Error(), "killed")
}