Implement pdeathSignal handling in Runc (#431)

Add support for parent death signal (pdeathSignal) to ensure child
processes receive a signal when the parent process dies. This addresses
the FIXME comment in Runc.execute().

## Changes
- Add pdeathSignal field to exec_command_attrs C struct
- Implement prctl(PR_SET_PDEATHSIG) in child process handler (Linux
only)
- Expose pdeathSignal through Command.Attrs Swift API
- Wire up pdeathSignal in Runc.execute() to remove FIXME

## Implementation Details
The implementation uses Linux-specific prctl() to set the parent death
signal, ensuring proper cleanup when parent processes terminate. The
feature is conditionally compiled for Linux only, maintaining
compatibility with other platforms.
This commit is contained in:
GAUTAM RAJU
2025-12-01 02:35:09 -08:00
committed by GitHub
parent 4a8f945f87
commit 031cd72e2a
4 changed files with 27 additions and 2 deletions
+13
View File
@@ -32,6 +32,9 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if defined(__linux__)
#include <sys/prctl.h>
#endif
#include "exec_command.h"
@@ -98,6 +101,7 @@ void exec_command_attrs_init(struct exec_command_attrs *attrs) {
attrs->mask = 0;
attrs->uid = -1;
attrs->gid = -1;
attrs->pdeathSignal = 0;
}
static void child_handler(const int sync_pipes[2], const char *executable,
@@ -253,6 +257,15 @@ static void child_handler(const int sync_pipes[2], const char *executable,
}
}
#if defined(__linux__)
// Set parent death signal if specified
if (attrs.pdeathSignal != 0) {
if (prctl(PR_SET_PDEATHSIG, attrs.pdeathSignal) != 0) {
goto fail;
}
}
#endif
// close exec everything outside of our child's fd_table.
if (cloexec_from(file_handle_count) != 0) {
goto fail;
+2
View File
@@ -38,6 +38,8 @@ struct exec_command_attrs {
gid_t gid;
/// signal mask for the child process
int mask;
/// parent death signal (Linux only, 0 to disable)
int pdeathSignal;
};
void exec_command_attrs_init(struct exec_command_attrs *attrs);
+9 -1
View File
@@ -68,6 +68,8 @@ public struct Command: Sendable {
public var uid: UInt32?
/// Set the process group ID.
public var gid: UInt32?
/// Signal to send when parent process dies (Linux only).
public var pdeathSignal: Int32?
public init(
setPGroup: Bool = false,
@@ -77,7 +79,8 @@ public struct Command: Sendable {
setsid: Bool = false,
setctty: Bool = false,
uid: UInt32? = nil,
gid: UInt32? = nil
gid: UInt32? = nil,
pdeathSignal: Int32? = nil
) {
self.setPGroup = setPGroup
self.resetIDs = resetIDs
@@ -87,6 +90,7 @@ public struct Command: Sendable {
self.setctty = setctty
self.uid = uid
self.gid = gid
self.pdeathSignal = pdeathSignal
}
}
@@ -207,6 +211,10 @@ extension Command {
attrs.gid = gid
}
if let pdeathSignal = self.attrs.pdeathSignal {
attrs.pdeathSignal = pdeathSignal
}
var pid: pid_t = 0
var argv = ([executable] + arguments).map { strdup($0) } + [nil]
defer {
+3 -1
View File
@@ -339,7 +339,9 @@ extension Runc {
cmd.stdout = stdout ?? outPipe.fileHandleForWriting
cmd.stderr = stderr ?? outPipe.fileHandleForWriting
// FIXME: pdeathSignal handling if Command supported it.
if let pdeathSignal = pdeathSignal {
cmd.attrs.pdeathSignal = pdeathSignal
}
if setpgid {
cmd.attrs.setPGroup = true