Skip to content

Commit

Permalink
libcontainer: Prevent startup hang when CloseExecFrom errors
Browse files Browse the repository at this point in the history
The previous logic caused runc to hang if CloseExecFrom returned an
error, as the defer waiting on logsDone never finished as the parent
process was never started (and it controls the closing of logsDone via
it's logsPipe).

This moves the defer to after we have started the parent, with means all
the logic related to managing the logsPipe should also be running.

Signed-off-by: Evan Phoenix <[email protected]>
  • Loading branch information
evanphx committed Jan 21, 2025
1 parent a7d7645 commit 7b26da9
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,6 @@ func (c *Container) start(process *Process) (retErr error) {
defer process.closeClonedExes()

logsDone := parent.forwardChildLogs()
if logsDone != nil {
defer func() {
// Wait for log forwarder to finish. This depends on
// runc init closing the _LIBCONTAINER_LOGPIPE log fd.
err := <-logsDone
if err != nil && retErr == nil {
retErr = fmt.Errorf("unable to forward init logs: %w", err)
}
}()
}

// Before starting "runc init", mark all non-stdio open files as O_CLOEXEC
// to make sure we don't leak any files into "runc init". Any files to be
Expand All @@ -348,6 +338,17 @@ func (c *Container) start(process *Process) (retErr error) {
return fmt.Errorf("unable to start container process: %w", err)
}

if logsDone != nil {
defer func() {
// Wait for log forwarder to finish. This depends on
// runc init closing the _LIBCONTAINER_LOGPIPE log fd.
err := <-logsDone
if err != nil && retErr == nil {
retErr = fmt.Errorf("unable to forward init logs: %w", err)
}
}()
}

if process.Init {
c.fifo.Close()
if c.config.HasHook(configs.Poststart) {
Expand Down

0 comments on commit 7b26da9

Please sign in to comment.