Merge pull request #4661 from lifubang/skip-setup-signalNotify-for-detached

skip setup signal notifier for detached container
This commit is contained in:
Rodrigo Campos Catelin
2026-04-02 13:50:34 +02:00
committed by GitHub
3 changed files with 50 additions and 44 deletions
+16
View File
@@ -151,6 +151,22 @@ func (s *notifySocket) run(pid1 int) error {
} }
} }
// forward reads systemd notifications from the container and forwards them
// to notifySocketHost.
func (s *notifySocket) forward(process *libcontainer.Process, detach bool) error {
if detach {
pid, err := process.Pid()
if err != nil {
return err
}
_ = s.run(pid)
} else {
_ = s.run(os.Getpid())
go func() { _ = s.run(0) }()
}
return nil
}
// notifyHost tells the host (usually systemd) that the container reported READY. // notifyHost tells the host (usually systemd) that the container reported READY.
// Also sends MAINPID and BARRIER. // Also sends MAINPID and BARRIER.
func notifyHost(client *net.UnixConn, ready []byte, pid1 int) error { func notifyHost(client *net.UnixConn, ready []byte, pid1 int) error {
+2 -26
View File
@@ -5,7 +5,6 @@ import (
"os/signal" "os/signal"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runc/libcontainer/utils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -16,15 +15,7 @@ const signalBufferSize = 2048
// newSignalHandler returns a signal handler for processing SIGCHLD and SIGWINCH signals // newSignalHandler returns a signal handler for processing SIGCHLD and SIGWINCH signals
// while still forwarding all other signals to the process. // while still forwarding all other signals to the process.
// If notifySocket is present, use it to read systemd notifications from the container and func newSignalHandler() chan *signalHandler {
// forward them to notifySocketHost.
func newSignalHandler(enableSubreaper bool, notifySocket *notifySocket) chan *signalHandler {
if enableSubreaper {
// set us as the subreaper before registering the signal handler for the container
if err := system.SetSubreaper(1); err != nil {
logrus.Warn(err)
}
}
handler := make(chan *signalHandler) handler := make(chan *signalHandler)
// Ensure that we have a large buffer size so that we do not miss any // Ensure that we have a large buffer size so that we do not miss any
@@ -41,7 +32,6 @@ func newSignalHandler(enableSubreaper bool, notifySocket *notifySocket) chan *si
signal.Notify(s) signal.Notify(s)
handler <- &signalHandler{ handler <- &signalHandler{
signals: s, signals: s,
notifySocket: notifySocket,
} }
}() }()
return handler return handler
@@ -56,32 +46,18 @@ type exit struct {
type signalHandler struct { type signalHandler struct {
signals chan os.Signal signals chan os.Signal
notifySocket *notifySocket
} }
// forward handles the main signal event loop forwarding, resizing, or reaping depending // forward handles the main signal event loop forwarding, resizing, or reaping depending
// on the signal received. // on the signal received.
func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach bool) (int, error) { func (h *signalHandler) forward(process *libcontainer.Process, tty *tty) (int, error) {
// make sure we know the pid of our main process so that we can return // make sure we know the pid of our main process so that we can return
// after it dies. // after it dies.
if detach && h.notifySocket == nil {
return 0, nil
}
pid1, err := process.Pid() pid1, err := process.Pid()
if err != nil { if err != nil {
return -1, err return -1, err
} }
if h.notifySocket != nil {
if detach {
_ = h.notifySocket.run(pid1)
return 0, nil
}
_ = h.notifySocket.run(os.Getpid())
go func() { _ = h.notifySocket.run(0) }()
}
// Perform the initial tty resize. Always ignore errors resizing because // Perform the initial tty resize. Always ignore errors resizing because
// stdout might have disappeared (due to races with when SIGHUP is sent). // stdout might have disappeared (due to races with when SIGHUP is sent).
_ = tty.resize() _ = tty.resize()
+30 -16
View File
@@ -20,6 +20,7 @@ import (
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/specconv" "github.com/opencontainers/runc/libcontainer/specconv"
"github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/runc/libcontainer/system/kernelversion" "github.com/opencontainers/runc/libcontainer/system/kernelversion"
"github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runc/libcontainer/utils"
) )
@@ -219,14 +220,16 @@ type runner struct {
subCgroupPaths map[string]string subCgroupPaths map[string]string
} }
func (r *runner) run(config *specs.Process) (int, error) { func (r *runner) run(config *specs.Process) (_ int, retErr error) {
var err error detach := r.detach || (r.action == CT_ACT_CREATE)
defer func() { defer func() {
if err != nil { // For a non-detached container, or we get an error, we
// should destroy the container.
if !detach || retErr != nil {
r.destroy() r.destroy()
} }
}() }()
if err = r.checkTerminal(config); err != nil { if err := r.checkTerminal(config); err != nil {
return -1, err return -1, err
} }
process, err := newProcess(config) process, err := newProcess(config)
@@ -255,11 +258,19 @@ func (r *runner) run(config *specs.Process) (int, error) {
} }
process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), "PreserveFD:"+strconv.Itoa(i))) process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), "PreserveFD:"+strconv.Itoa(i)))
} }
detach := r.detach || (r.action == CT_ACT_CREATE)
// Setting up IO is a two stage process. We need to modify process to deal // Setting up IO is a two stage process. We need to modify process to deal
// with detaching containers, and then we get a tty after the container has // with detaching containers, and then we get a tty after the container has
// started. // started.
handlerCh := newSignalHandler(r.enableSubreaper, r.notifySocket) if r.enableSubreaper {
// set us as the subreaper before registering the signal handler for the container
if err := system.SetSubreaper(1); err != nil {
logrus.Warn(err)
}
}
var handlerCh chan *signalHandler
if !detach {
handlerCh = newSignalHandler()
}
tty, err := setupIO(process, r.container, config.Terminal, detach, r.consoleSocket) tty, err := setupIO(process, r.container, config.Terminal, detach, r.consoleSocket)
if err != nil { if err != nil {
return -1, err return -1, err
@@ -287,29 +298,32 @@ func (r *runner) run(config *specs.Process) (int, error) {
if err != nil { if err != nil {
return -1, err return -1, err
} }
if err = tty.waitConsole(); err != nil { defer func() {
// We should terminate the process once we got an error.
if retErr != nil {
r.terminate(process) r.terminate(process)
}
}()
if err = tty.waitConsole(); err != nil {
return -1, err return -1, err
} }
tty.ClosePostStart() tty.ClosePostStart()
if r.pidFile != "" { if r.pidFile != "" {
if err = createPidFile(r.pidFile, process); err != nil { if err = createPidFile(r.pidFile, process); err != nil {
r.terminate(process)
return -1, err return -1, err
} }
} }
handler := <-handlerCh if r.notifySocket != nil {
status, err := handler.forward(process, tty, detach) if err = r.notifySocket.forward(process, detach); err != nil {
if err != nil { return -1, err
r.terminate(process) }
} }
if detach { if detach {
return 0, nil return 0, nil
} }
if err == nil { // For non-detached container, we should forward signals to the container.
r.destroy() handler := <-handlerCh
} return handler.forward(process, tty)
return status, err
} }
func (r *runner) destroy() { func (r *runner) destroy() {