Email or username:

Password:

Forgot your password?
rain 🌦️

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!

sunshowers.io/posts/beyond-ctr

18 comments
rain 🌦️

Usually someone else ends up submitting my posts on HN, but I decided to do so for once: news.ycombinator.com/item?id=4

Paul Jewell

@rain
Thanks for sharing! Very interesting read

jyn

@rain

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

@rain

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

rain 🌦️

@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

jyn

@rain wait i am confused, isn't doc.rust-lang.org/std/task/ind for working with async blocks?

rain 🌦️

@jyn oh I'm referring to futures vs tasks -- futures need to be driven externally while tasks are driven by the executor to completion

jyn

@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

rain 🌦️

@jyn Rust actually has both models! futures are async blocks or manual impls, tasks are futures given to the executor to run

rain 🌦️

@jyn And yes JS only has the latter model -- every JS async call is a tokio::spawn basically

rain 🌦️

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

@rain @jyn interesting, why was an executor trampoline necessary when recursing across an arbitrary-depth graph?

rain 🌦️

@predrag @jyn Oh well, if you just await on a (boxed) child future you'll end up with an arbitrary-depth pointer stack -- so you need to go up to the top every so often

(We're talking 10 million+ depth)

Predrag Gruevski replied to rain

@rain @jyn I figured it was something like that, but I haven't used nearly enough async Rust yet to be able to construct the precise counterexample in my head.

Thanks!

rain 🌦️ replied to Predrag

@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 Gruevski replied to rain

@rain @jyn how does one recover the results of each task in this case?

mpsc shenanigans? Or something more elegant?

rain 🌦️ replied to rain

@predrag @jyn Oneshot channels are kind of the bread and butter of async communication, because they're equivalent to calling a function and getting a return value back

Go Up