in internal/kernel/process/process.go [239:300]
func (p *Process) Close() {
if p.closed {
return
}
// Acquire the lock, so we don't try to concurrently close multiple times
p.mutex.Lock()
defer p.mutex.Unlock()
// Check again now that we own the lock, it may be a fast exit!
if p.closed {
return
}
if p.stdin != nil {
// Try to send the exit message, this might fail, but we can ignore that.
p.stdin.Write([]byte("{\"exit\":0}\n"))
// Close STDIN for the child process now. Ignoring errors, as it may
// have been closed already (e.g: if the process exited).
p.stdin.Close()
p.stdin = nil
}
if p.stdout != nil {
// Close STDOUT for the child process now, as we don't expect to receive
// responses anymore. Ignoring errors, as it may have been closed
// already (e.g: if the process exited).
p.stdout.Close()
p.stdout = nil
}
if p.stderrDone != nil {
// Wait for the stderr sink goroutine to have finished
<-p.stderrDone
p.stderrDone = nil
}
if p.stderr != nil {
// Close STDERR for the child process now, as we're no longer consuming
// it anyway. Ignoring errors, as it may havebeen closed already (e.g:
// if the process exited).
p.stderr.Close()
p.stderr = nil
}
if p.cmd != nil {
// Wait for the child process to be dead and gone (should already be)
p.cmd.Wait()
p.cmd = nil
}
if p.tmpdir != "" {
// Clean up any temporary directory we provisioned.
if err := os.RemoveAll(p.tmpdir); err != nil {
fmt.Fprintf(os.Stderr, "could not clean up temporary directory: %v\n", err)
}
p.tmpdir = ""
}
p.closed = true
}