Skip to content

Eliminate setjmp / longjmp #10

Description

@fstirlitz

One design decision I made here that I’ve come to regret is basing error handling on setjmp/longjmp; I did this, somewhat embarrassingly, mostly for the sake of syntactic convenience. This pair of functions causes a number of headaches:

  • They are somewhat expensive: setjmp has to write the whole register file into jmp_buf, which is 200 bytes on x86-64 and 156 on x86-32;
  • They are hard for static analysers to reason about: I have seen cppcheck emit a spurious warning about using an uninitialised struct bsp_ec in the error branch, even though I know bsp_die would initialise it;
  • They are hard to use safely: there are some hazards with setjmp clobbering variables stored in registers that I haven’t read much on; to avoid those, one should declare all local variables at the setjmp call site volatile. I only manage to get away with not doing this because glibc marks setjmp with a returns_twice attribute that ensures no variables are stored in registers across this function call. (I didn’t want to apply this attribute in my own code though, which is why bsp_try is a macro and not a function.)
  • They may cause issues in code that isn’t aware of them: each time I write code that may be longjmped over, I must be careful not to introduce resource leaks. The implementation of the menu opcode is one example where the code is much more complicated than I’d like: I have to create another error context just to be able to free the memory allocation and pass the error along using bsp_rethrow.

I should probably switch to using error codes as return values. They aren’t too pretty, but they are at least safer.

(Good thing I haven’t committed to a stable API/ABI yet!)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions