From c07c0c810f0304a18670f7b87821285124ba5bce Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Tue, 23 Apr 2019 09:22:48 -0400 Subject: [PATCH] fix crash when executor parent nomad process dies Fixes https://github.com/hashicorp/nomad/issues/5593 Executor seems to die unexpectedly after nomad agent dies or is restarted. The crash seems to occur at the first log message after the nomad agent dies. To ease debugging we forward executor log messages to executor.log as well as to Stderr. `go-plugin` sets up plugins with Stderr pointing to a pipe being read by plugin client, the nomad agent in our case[1]. When the nomad agent dies, the pipe is closed, and any subsequent executor logs fail with ErrClosedPipe and SIGPIPE signal. SIGPIPE results into executor process dying. I considered adding a handler to ignore SIGPIPE, but hc-log library currently panics when logging write operation fails[2] This we opt to revert to v0.8 behavior of exclusively writing logs to executor.log, while we investigate alternative options. [1] https://github.com/hashicorp/nomad/blob/v0.9.0/vendor/github.com/hashicorp/go-plugin/client.go#L528-L535 [2] https://github.com/hashicorp/nomad/blob/v0.9.0/vendor/github.com/hashicorp/go-hclog/int.go#L320-L323 --- command/executor_plugin.go | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/command/executor_plugin.go b/command/executor_plugin.go index 2ba041dff02..0e4cfadb421 100644 --- a/command/executor_plugin.go +++ b/command/executor_plugin.go @@ -2,7 +2,6 @@ package command import ( "encoding/json" - "io" "os" "strings" @@ -11,17 +10,9 @@ import ( plugin "github.com/hashicorp/go-plugin" "github.com/hashicorp/nomad/drivers/shared/executor" - "github.com/hashicorp/nomad/lib/circbufwriter" "github.com/hashicorp/nomad/plugins/base" ) -const ( - // circleBufferSize is the size of the in memory ring buffer used for - // go-plugin logging to stderr. When the buffer exceeds this size before - // flushing it will begin overwriting data - circleBufferSize = 64 * 1024 -) - type ExecutorPluginCommand struct { Meta } @@ -55,20 +46,11 @@ func (e *ExecutorPluginCommand) Run(args []string) int { return 1 } - // If the client detatches from go-plugin it will block on logging to stderr. - // This buffered writer will never block on write, and instead buffer the - // writes to a ring buffer. - bufferedStderrW := circbufwriter.New(os.Stderr, circleBufferSize) - - // Tee the logs to stderr and the file so that they are streamed to the - // client - out := io.MultiWriter(f, bufferedStderrW) - // Create the logger logger := log.New(&log.LoggerOptions{ Level: hclog.LevelFromString(executorConfig.LogLevel), JSONFormat: true, - Output: out, + Output: f, }) plugin.Serve(&plugin.ServeConfig{