i have a tool written in Swift that occasionally traps on precondition failure. changing the tool so that it never traps is not realistic, and is also not desirable. therefore, i would like to run the tool as a child process to allow for cleanup and recovery if the tool crashes.
the tool has a complex interface, so i do not want to write a command line argument parser for it. is there a simpler way to run a Swift function in a child process?
1 Like
jrose
(Jordan Rose)
2
This is probably not a good answer, but it would be fun to make a distributed actor provider that did that. The reason my mind went there is because all the structure is there to handle the argument/result serialization and asynchrony.
More practically, however, @grynspan’s experiments with “death tests” might have a way forward. I haven’t looked at the implementation there, though. Add experimental exit test support. by grynspan · Pull Request #307 · apple/swift-testing · GitHub
4 Likes
grynspan
(Jonathan Grynspan)
3
My experimental implementation just uses Process, so that's probably not what I'd call "lightweight." But I am eager to explore how distributed actors could be used instead for the same purpose.
@ktoso knows far more about what's possible with them than I do.
1 Like
tera
4
I'd love to try that. A first naive question - does it work on iOS? IIRC before we were limited to one process per app (excluding extensions for things like QuickLook previewing, audio units, sharing, etc).
jrose
(Jordan Rose)
5
I was thinking you’d still implement it on top of Process, at least for now, so no.
Joe_Groff
(Joe Groff)
6
If the subtask doesn't need to also run as native code, and can run within the limits of the platform, another thing to try might be to build it as wasm and run it in a wasm host. wasm might be an interesting way of building the "in process distributed actor host" concept Jordan alluded to.
4 Likes
tera
7
Looks are are in need of some new "Actor Application extension" then...
grynspan
(Jonathan Grynspan)
8
FYI I've actually merged that PR and started a thread in the forums for anybody who wants to try it out and discuss.
1 Like
orobio
(Manolo van Ee)
9
My first thought was: that’s just a fork. A quick search on ‘fork without exec’ shows that you have to be very careful with it though, but perhaps it’s usable in your situation.
eskimo
(Quinn “The Eskimo!”)
10
A quick search on ‘fork without exec’ shows that you have to
be very careful with it though
Indeed. IMO you you can’t reliably combine fork without exec* and Swift. This has come up a few times on DevForums, like here and here.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
3 Likes
Any chance that implementation can become its own library? I really need something like that for a project I'm currently working on. Right now I'm using Process which accepts data as a blob of serialised stuff. This is much less ergonomic than using something like your implementation and obviously more bug prone
eskimo
(Quinn “The Eskimo!”)
12
Any chance that implementation can become its own library?
Why, yes!
The Foundation folks are in the process (hey hey) of creating a replacement for Process. See [Pitch] Swift Subprocess. I don’t think there’s any ETA for that yet, but it’s definitely on the cards.
In the meantime, there are a number of alternative Process wrappers from other third-party developers. I don’t keep track of them — due to the nature of my work, I’m not able to use third-party libraries — so I can’t give you a specific recommendation. Perhaps someone else will chime in…
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
1 Like
Subprocess still can't run a swift function inside it though. I'm working on a project where it would be highly beneficial to do just that. For now, I'm using a multicall binary and a bincode-encoded blob of data to pass it all the needed information. This works fine, but feels pretty junky. So an ability to run a function in a subprocess would be incredibly nice to have. See: procspawn — Rust data encoding library // Lib.rs as an example
1 Like
ktoso
(Konrad 'ktoso' Malawski 🐟🏴☠️)
14
What you're describing sounds very similar to a distributed actor system that is being discussed here -- Runtime extensibility via distributed actors - #2 by ktoso
We'd have a binary that we launch and enter the "child process mode" and communicate with it. You could have a distributed actor encapsulate your (distributed) function and this way invoke it in the child process. It doesn't have to be the same binary, but we could think of such way -- I had old old old prototypes with just that in the distributed actors library from way before we even had actors in the language, for inspiration. We could do this much nicer today with (distributed) actors being part of the language though 
I invite you to join the discussion in the Runtime extensibility via distributed actors thread!
grynspan
(Jonathan Grynspan)
15
The implementation in swift-testing's proof-of-concept exit tests feature is probably not possible to factor into a library as-is. It depends on some pretty deep/arcane knowledge of the Swift runtime's emitted metadata. @ktoso's distributed actors work is probably closer to a general-purpose solution.
1 Like