You might find that Fil-C prevents those too. It’s pretty strict. You can only use longjmp to pop stack like an exception would
Edit: The extra context- https://usenix.org/legacy/publications/library/proceedings/u...
Fil-C also makes sigaction memory safe. That protection does allow for signal handlers to longjmp or setcontext or swapcontext
I suppose managing the stack is still managing memory after all, even if we typically don't think of it that way, so Fil-C has something to add here.
It's really worth reading the section here about the complexity of setjmp/longjmp and how they interact with register allocation and stack spilling. I knew they're tricky, but going in to the specifics is delicious.
Maybe for the incredibly slow fallback, it does. Boost context and Boost fiber has ABI support for *nix / MacOS / Windows for x86_64 and ARM/ARM64. The overhead for a fiber switch using this support is about as heavy as a virtual function call. In comparison, ucontext is very heavy.
I wrote my own fiber library for C. I got the idea from an old implementation I saw that used setjmp and longjmp, which took me down the rabbit hole of figuring out how to do this more efficiently and with an improved margin of safety. I chose to follow Boost's example, and in fact, used some of their fiber switch assembler with attribution in my library.
It's heavy because it switches the signal masks.
Indeed, Fil-C's ucontext logic does this today, because I'm relying on glibc, and that's what glibc does.
But it would be straightforward to teach the internal Fil-C zfiber_context API to not save the sigmasks. It would just mean using some other backend for setcontext/swapcontext. Considering that there are multiple open source projects (including Boost!) that have code that does this, it would be easy to set that up.
But I'm taking baby steps here. And the first step is just to provide a memory safe wrapper around these quite dangerous APIs. Probably the next step is to just write a lot more tests to try to break it. Then, later, I can worry about adding alternative backends to expose the sigmask-free version of this that Boost (and most others) want.
To do this, I disable signals on threads that are fiber threads, and instead rely on a signal thread to intercept signals and alert the appropriate fibers.
> Hence, the most basic safety issue with setjmp is that if we call it and then return from the function that had called it, the context saved by setjmp is not valid to longjmp to.
> longjmp is only safe if it's called at a time when the stack frame used by setjmp could not have possibly been overwritten, since that is the only way to guarantee that the register state restored by longjmp matches the stack frame that the stack pointer points to.
That limitation could be lifted by simply copying the stack frames somewhere else prior to long jumping, and then spilling that entire thing on top of the current stack instead of just restoring the registers in from the jump buffer. This is how delimited continuations work! What ruins this for C is the existence of pointers. Stacks aren't freely relocatable since pointers into the stack could exist. Other languages don't have this problem.
So much fun stuff in this article! The "fibers with ucontext", essentially swapping stack pointers back and forth, are how I implemented generators! I too reached for musl source code in order to understand setjmp, but for a different reason: its ability to spill the registers onto the stack was instrumental for my garbage collector.
Blogged about all of these things too, in case anyone is curious:
https://www.matheusmoreira.com/articles/delimited-continuati...
https://www.matheusmoreira.com/articles/generators-in-lone-l...
https://www.matheusmoreira.com/articles/babys-second-garbage...
What about languages with pass by reference?
brcmthrowaway•59m ago
bitbasher•54m ago
https://github.com/pizlonator/fil-c/blob/deluge/CLAUDE.md
pizlonator•19m ago
I have used Kimi K2.6-code and GLM 5.2, but only for things that are easy to verify. I did not use any LLMs for the longjmp/ucontext work.