LLM disclosure: I use LLMs mainly to aid with debugging and for generating code for auxiliary parts of the system. I have used it in core areas on occasion though.
Hello! I’ve been working on an interpreter for a while, Zicl. I’ve recently started adding IO support, and as such am starting to use the 0.16 Io API, specifically the Threaded implementation. The issue I’ve run into while using Threaded is how to incorporate cancelation within an existing C project.
For context, I’m currently developing this interpreter to embed in my fork of folk.computer. I’ve been struggling to figure out how Threaded will interact with Folk’s scheduler. Folk’s scheduler is similar to Go, in that tasks are allowed to block the thread (and it’ll spin up more threads to make forward progress). When a task needs to be canceled, Folk sends SIGUSR1 to that task’s thread, which unblocks the thread’s IO and winds down its interpreter state.
Since tasks are scheduled by Folk, my interpreter is called from C, from a thread managed by C, with cancelation initiated from C via SIGUSR1. The problem is Zig’s Threaded ignores signals that weren’t initiated from the Zig side as part of canceling, so it’ll just restart the syscall if thread.status.cancelation hasn’t been set. This means by default Threaded will ignore the cancelation from Folk. So I need some way to make Zig aware of the cancelation, from the Zig side. I looked into using async and cancel for that, but the Future docs say that cancelation is not threadsafe, so I wouldn’t be able to pass a Future to another thread to cancel the blocking operation.
I briefly looked into what it would take to implement my own Io, but considering how much code went into the Threaded implementation I think it’s a non-starter. The two (bad) options I’ve figured out so far are 1. Vendoring Threaded and rewriting the Syscall helper, and 2. creating a frankenstein Io interface that selectively overrides functions in the current Threaded vtable with functions that respect Folk’s cancelation model. I’m not super happy with either though.
Is there a better way to handle cancelation from C threads? It doesn’t need to cancel via SIGUSR1 specifically, but there needs to be some way to have the threads managed by C, and also to be able to initiate cancelation from another C thread. Thanks in advance!