There shouldn’t really be a distinction here: killing the parent process on Linux should not kill the children any more than it does on macOS. Are you confident the child has spawned when you kill the parent? Is the child dying for some other reason, e.g. SIGPIPE on one of stdin/stdout/stderr?
@lukasa I did a bit more digging, and it looks like Swift on macOS puts the subprocess into its own process group, whereas on Linux the process stays in the parent’s group.
import Foundation
let pid = ProcessInfo.processInfo.processIdentifier
print("Swift PID: \(pid)")
let perl = Process()
perl.executableURL = URL( fileURLWithPath: "/usr/bin/perl" )
perl.arguments = ["-Mstrict", "-w", "-E", "say q<perl pgrp: > . getpgrp; say($$) && sleep 1 while 1"]
try perl.run()
perl.waitUntilExit()
macOS:
Swift PID: 66819
perl pgrp: 66820
66820
66820
66820
Linux (Raspbian):
Swift PID: 10026
perl pgrp: 10026
10030
10030
10030
This explains why on Linux the child process receives SIGINT while on macOS the child process outlives its parent: the child process belongs to a different process group and so doesn’t receive the same SIGINT that the parent receives from the CTRL-C.
I’ve looked in vain for a comparable tool on macOS … do you know of
any?
The weapon of choice for this sort of macOS is DTrace. For example, both sigdist.d and kill.d are based on this.
Unfortunately this weapon is somewhat blunted on modern systems by system integrity protection (SIP). I don’t want to disable SIP on my main machine so I generally do my DTrace work in a VM where I have a snapshot with SIP-disabled.
I think the inconsistency is a bug: which way around the bug goes is a matter for the Foundation team. @millenomi, do you have thoughts here? Does this difference warrant a bugs.swift.org or a Feedback?