WARNING: this crate is experimental and even careful use is likely undefined behavior.
This crate exposes four C standard library functions to Rust:
pub fn setjmp(env: *mut jmp_buf) -> c_int;
pub fn sigsetjmp(env: *mut sigjmp_buf, savesigs: c_int) -> c_int;
pub fn longjmp(env: *mut jmp_buf, val: c_int) -> c_void;
pub fn siglongjmp(env: *mut sigjmp_buf, val: c_int) -> c_void;
as well as the jmp_buf
and sigjmp_buf
types needed to use them.
See setjmp(3)
for details and caveats.
Also see RFC #2625.
Beyond the many caveats and challenges using setjmp/longjmp
in C, there are additional challenges using them from rust.
longjmp()
must be careful to not jump over any stack frame that owns references to variables that have destructors.fork()
or setjmp()
, so it's easy to imagine that rust might generate incorrect code around such a function.returns_twice
attribute; but rust has no way to propagate that attribute to LLVM. Without this attribute, it's possible that LLVM itself will generate incorrect code.With so many problems, why is it worth dealing with setjmp
/longjmp
? Because it's sometimes important when interacting with existing C code or APIs.
longjmp()
happens, you may want the rust code to catch, the longjmp()
, transform it into a panic (to safely unwind), then catch_unwind()
, then turn it back into a longjmp()
to return to someplace in the C code (the last place that called setjmp()
).longjmp()
from the C code and handle it somehow.longjmp()
to return control to C code.If the caveats so far haven't scared you away, and you'd like to get even more dangerous, you could also:
setjmp()
/longjmp()
just as a control flow mechanism in rust, without C being involved.Ordinarily, using a C function from rust is easy: you just declare it. Why go to the trouble of making a special crate?
jmp_buf
and sigjmp_buf
types are not trivial and are best defined using bindgen on the system's <setjmp.h>
header.sigsetjmp
the actual libc symbol might be __sigsetjmp
, and there may be a macro to rewrite the sigsetjmp()
call into __sigsetjmp()
.