mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
fix systemd-notify when using a different PID namespace
The current support of systemd-notify has a race condition as the message send to the systemd notify socket might be dropped if the sender process is not running by the time systemd checks for the sender of the datagram. A proper fix of this in systemd would require changes to the kernel to maintain the cgroup of the sender process when it is dead (but it is not probably going to happen...) Generally, the solution to this issue is to specify the PID in the message itself so that systemd has not to guess the sender, but this wouldn't work when running in a PID namespace as the container will pass the PID known in its namespace (something like PID=1,2,3..) and systemd running on the host is not able to map it to the runc service. The proposed solution is to have a proxy in runc that forwards the messages to the host systemd. Example of this issue: https://github.com/projectatomic/atomic-system-containers/pull/24 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
+15
-3
@@ -17,7 +17,9 @@ const signalBufferSize = 2048
|
||||
|
||||
// newSignalHandler returns a signal handler for processing SIGCHLD and SIGWINCH signals
|
||||
// while still forwarding all other signals to the process.
|
||||
func newSignalHandler(enableSubreaper bool) *signalHandler {
|
||||
// If notifySocket is present, use it to read systemd notifications from the container and
|
||||
// forward them to notifySocketHost.
|
||||
func newSignalHandler(enableSubreaper bool, notifySocket *notifySocket) *signalHandler {
|
||||
if enableSubreaper {
|
||||
// set us as the subreaper before registering the signal handler for the container
|
||||
if err := system.SetSubreaper(1); err != nil {
|
||||
@@ -30,7 +32,8 @@ func newSignalHandler(enableSubreaper bool) *signalHandler {
|
||||
// handle all signals for the process.
|
||||
signal.Notify(s)
|
||||
return &signalHandler{
|
||||
signals: s,
|
||||
signals: s,
|
||||
notifySocket: notifySocket,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +45,8 @@ type exit 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
|
||||
@@ -54,6 +58,11 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty) (int, e
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if h.notifySocket != nil {
|
||||
go h.notifySocket.run()
|
||||
}
|
||||
|
||||
// perform the initial tty resize.
|
||||
tty.resize()
|
||||
for s := range h.signals {
|
||||
@@ -75,6 +84,9 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty) (int, e
|
||||
// status because we must ensure that any of the go specific process
|
||||
// fun such as flushing pipes are complete before we return.
|
||||
process.Wait()
|
||||
if h.notifySocket != nil {
|
||||
h.notifySocket.Close()
|
||||
}
|
||||
return e.status, nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user