package exec import ( "context" "strconv" "sync" "time" hclog "github.com/hashicorp/go-hclog" plugin "github.com/hashicorp/go-plugin" "github.com/hashicorp/nomad/drivers/shared/executor" "github.com/hashicorp/nomad/plugins/drivers" ) type taskHandle struct { exec executor.Executor pid int pluginClient *plugin.Client logger hclog.Logger // stateLock syncs access to all fields below stateLock sync.RWMutex taskConfig *drivers.TaskConfig procState drivers.TaskState startedAt time.Time completedAt time.Time exitResult *drivers.ExitResult } func (h *taskHandle) TaskStatus() *drivers.TaskStatus { h.stateLock.RLock() defer h.stateLock.RUnlock() return &drivers.TaskStatus{ ID: h.taskConfig.ID, Name: h.taskConfig.Name, State: h.procState, StartedAt: h.startedAt, CompletedAt: h.completedAt, ExitResult: h.exitResult, DriverAttributes: map[string]string{ "pid": strconv.Itoa(h.pid), }, } } func (h *taskHandle) IsRunning() bool { h.stateLock.RLock() defer h.stateLock.RUnlock() return h.procState == drivers.TaskStateRunning } func (h *taskHandle) run() { h.stateLock.Lock() if h.exitResult == nil { h.exitResult = &drivers.ExitResult{} } h.stateLock.Unlock() // Block until process exits ps, err := h.exec.Wait(context.Background()) h.stateLock.Lock() defer h.stateLock.Unlock() if err != nil { h.exitResult.Err = err h.procState = drivers.TaskStateUnknown h.completedAt = time.Now() return } h.procState = drivers.TaskStateExited h.exitResult.ExitCode = ps.ExitCode h.exitResult.Signal = ps.Signal h.completedAt = ps.Time // TODO: detect if the task OOMed }