[Review] SF-0007: Introducing Swift Subprocess

I did a quick-and-dirty test of this API in my Shwift package:

Passing 3 for lowfiledes does indeed close file descriptors (can be tested via ScriptExample's stressTest). Unfortunately, passing 0 and then duping some file descriptors does not result in those descriptors being open in the child process.

What this means is for the common case where we just care about stdin, stdout and stderr this will work fine. In the less common case where you are passing another file descriptor things get murky. As you see in the example, simply closing a range of file descriptors seems to work, so if the file descriptor you want to pass has a value of "42" you can do for i in 3..<42 { ps_..._close(42) }; ps_closefrom(43). If you want to pass a file descriptor with the value of UInt32.max for some ungodly reason, this becomes less reasonable.

Given all of this, maybe the right approach is to use closefrom if the file descriptors that you want to pass are consecutive from 0, and throw ENOSYS if the file descriptors are nonconsecutive (similar to how ENOSYS is thrown here in tools-support-core). This would make it work for almost all use cases (I can't come up with a practical example where you would want to pass an extra file descriptor with a high numeric value) but will fail explicitly if the API consumer requests something weird that can't be robustly supported.

Update: Polished this up and added it to Shwift, seems to be working great!

1 Like