Script behaves differently on RPi than on macOS

Hello,

I’m getting started with Swift scripting, and I’m seeing different behavior on macOS (swift 5.0.1) than on Raspbian (swift 5.1.5).

The script is:

#!/usr/bin/env swift

import Foundation

let perl = Process()
perl.executableURL = URL( fileURLWithPath: "/usr/bin/perl" )
perl.arguments = ["-Mstrict", "-w", "-E", "say(1) && sleep 1 while 1"]

try perl.run()

perl.waitUntilExit()

When I CTRL-C that on Raspbian, the Perl subprocess stops. But when I CTRL-C it on macOS, the subprocess keeps going.

Does one platform move the subprocess to a different process group, or what would explain the difference?

Thank you!

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?

strace (Linux) shows that both the Swift and Perl processes receive SIGINT, and that signal ends both processes.

I’ve looked in vain for a comparable tool on macOS … do you know of any?

@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.

Do you think the Linux behavior is a bug?

1 Like

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.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

2 Likes

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?

FWIW, as a longtime *nix programmer I’d expect the child process to inherit its parent’s process group (i.e., the behaviour I see in Swift/Linux).

1 Like

FYI, I’ve reported this:
https://bugs.swift.org/browse/SR-13861