New blog post! Beyond Ctrl-C: The dark corners of Unix signal handling.
The post is an introduction to signals and how to manage them effectively with async Rust. It's a written version of my talk at RustConf 2023, heavily edited for presentation as a blog post.
Hope you enjoy reading it as much as I enjoyed writing it!
Here's the talk, in case you missed it:
Usually someone else ends up submitting my posts on HN, but I decided to do so for once: https://news.ycombinator.com/item?id=41437824
@rain
Thanks for sharing! Very interesting read
The functions okay to call in signal handlers are called async-signal-safe functions. The term is a bit confusing! “async” here has nothing to do with async Rust. (In many ways it’s the opposite of async Rust, because the defining characteristic of async Rust is that you cannot just be interrupted or preempted at any time. You can only be interrupted at await points.)
in some ways i wish rust (and javascript before it) had settled on "cooperative multi-tasking" as the name to call it
"async" is not a good intuition because so many things can be asynchronous idk. "multi-tasking" even has a nice task {}
abbreviation you can use for the blocks that i think semantically describes what the closure is doing better
@jyn Hmm, well at least in Rust tasks are quite different, though I guess there would have been a different name for them in that world
@rain wait i am confused, isn't https://doc.rust-lang.org/std/task/index.html for working with async blocks?
@jyn oh I'm referring to futures vs tasks -- futures need to be driven externally while tasks are driven by the executor to completion
@rain ahh got it
hmm i think i haven't heard that distinction using those words, i know rust has the first model and javascript has the latter but i've always considered "future" and "task" synonymous until now
@jyn Rust actually has both models! futures are async blocks or manual impls, tasks are futures given to the executor to run
@jyn And yes JS only has the latter model -- every JS async call is a tokio::spawn basically
@jyn (When I first started writing async Rust, with futures 0.1, I didn't understand the difference until almost a year in lol...
the first time I used an executor, it was to trampoline a recursive traversal of an arbitrary-depth graph, not to run pieces of code in parallel
@predrag @jyn let's say you're traversing a Merkle linked list (in this case a chain of source control commits) to fold over them recursively -- if you just create a child future with the recursive call then await it, your task stack will grow in an unbounded fashion. If you spawn a new task for each node instead, this isn't an issue
@predrag @jyn Good question! This is best modeled by a oneshot channel: https://docs.rs/tokio/latest/tokio/sync/oneshot/index.html
@sjb thank you for the very kind words! I'm happy that something I enjoy is so valuable to folks