setjmp(3)

โœจ setjmp(3) โœจ

okay bestie, welcome to the Library Functions Manual page for setjmp(3) ๐Ÿซถ this one's a whole vibe โ€” it's about jumping around your program in ways that are either extremely powerful or extremely cursed depending on how you hold it. buckle up ๐Ÿ’–


๐ŸŒธ NAME ๐ŸŒธ

setjmp, sigsetjmp, longjmp, siglongjmp โ€” performing a nonlocal goto


๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc)


๐ŸŽ€ SYNOPSIS ๐ŸŽ€

#include <setjmp.h>

int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int savesigs);

[[noreturn]] void longjmp(jmp_buf env, int val);
[[noreturn]] void siglongjmp(sigjmp_buf env, int val);

๐Ÿ” Feature Test Macro Requirements for glibc (see feature_test_macros(7)): ๐Ÿ”

setjmp(): see HISTORY.

sigsetjmp():
    _POSIX_C_SOURCE

๐Ÿ’ซ DESCRIPTION ๐Ÿ’ซ

so here's the tea โ˜• โ€” everything on this page is about doing a "nonlocal goto": yeeting execution out of one function and landing it at a predetermined spot inside a totally different function. feral behaviour, frankly, but sometimes you need it ๐Ÿ’…

  • setjmp() sets up the target โ€” where control will eventually get teleported to.
  • longjmp() does the actual teleport.

๐ŸŒˆ setjmp() ๐ŸŒˆ

setjmp() saves a bunch of info about the calling environment into the buffer env, so longjmp() can use it later. What exactly gets saved? Typically the stack pointer, the instruction pointer, possibly the values of other registers, and the signal mask. iykyk ๐Ÿฆ‹

In this case โ€” the normal, non-teleported one โ€” setjmp() returns 0.

๐ŸŒˆ longjmp() ๐ŸŒˆ

longjmp() takes the info saved in env and transfers control back to the point where setjmp() was called, restoring ("rewinding") the stack to how it looked back at that setjmp() call. and depending on the implementation (peep NOTES and HISTORY, bestie) the values of some other registers and the process signal mask may also get restored to their state at the time of that setjmp() call.

After a successful longjmp(), execution continues as if setjmp() had returned for a second time. iconic ๐Ÿ˜ญ This "fake" return is distinguishable from a real setjmp() call because the "fake" return returns the value you passed in val.

โš ๏ธ and if you (oops) pass 0 in val? the "fake" return will instead return 1. no cap.

๐Ÿฆ‹ sigsetjmp() and siglongjmp() ๐Ÿฆ‹

sigsetjmp() and siglongjmp() also do nonlocal gotos, but they give you predictable handling of the process signal mask. that's the whole point of them, periodt.

If, and only if, the savesigs argument handed to sigsetjmp() is nonzero: the process's current signal mask is saved in env, and it'll be restored if a siglongjmp() is later performed with that same env. ๐Ÿ’พ


๐ŸŽ RETURN VALUE ๐ŸŽ

setjmp() and sigsetjmp() return 0 when called directly. on the "fake" return that happens after longjmp() or siglongjmp(), the nonzero value you specified in val is what comes back ๐Ÿ’ซ

and the longjmp() or siglongjmp() functions themselves? they do not return. like, at all. ๐Ÿ‘ป


๐Ÿ”ฅ ATTRIBUTES ๐Ÿ”ฅ

for an explanation of the terms used in this section, see attributes(7). the original page ships a lil table; here it is as the same facts in list form, bestie:

  • setjmp(), sigsetjmp() โ€” Thread safety โ€” MT-Safe
  • longjmp(), siglongjmp() โ€” Thread safety โ€” MT-Safe

๐Ÿ‘‘ STANDARDS ๐Ÿ‘‘

  • setjmp(), longjmp() โ€” C11, POSIX.1-2008.
  • sigsetjmp(), siglongjmp() โ€” POSIX.1-2008.

๐Ÿ“œ HISTORY ๐Ÿ“œ

  • setjmp(), longjmp() โ€” POSIX.1-2001, C89.
  • sigsetjmp(), siglongjmp() โ€” POSIX.1-2001.

now for the lore, because this is where it gets spicy ๐ŸŒถ๏ธ

POSIX does not specify whether setjmp() will save the signal mask (to be later restored during longjmp()). like, it just. doesn't say. so it varies:

  • In System V it will not.
  • In 4.3BSD it will, and there's a function _setjmp() that will not.

The behavior under Linux depends on the glibc version and the setting of feature test macros:

  • Before glibc 2.19: setjmp() follows the System V behavior by default, but the BSD behavior is provided if the _BSD_SOURCE feature test macro is explicitly defined and none of _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _GNU_SOURCE, or _SVID_SOURCE is defined.
  • Since glibc 2.19: <setjmp.h> exposes only the System V version of setjmp().

so if your program needs the BSD semantics now? replace calls to setjmp() with calls to sigsetjmp() with a nonzero savesigs argument. that's the move ๐Ÿ’…


๐Ÿงš NOTES ๐Ÿงš

setjmp() and longjmp() can be genuinely useful for dealing with errors inside deeply nested function calls ๐Ÿ“š โ€” or to let a signal handler pass control to a specific point in the program, instead of just returning to wherever the handler interrupted the main program.

In that latter case, if you want to portably save and restore signal masks, use sigsetjmp() and siglongjmp(). ๐Ÿซถ and also peep the discussion of program readability below, because it's lowkey a warning in disguise.


๐Ÿ’€ CAVEATS ๐Ÿ’€

okay this is the part where you sit down, bestie. ๐Ÿช‘

The compiler may optimize variables into registers, and longjmp() may restore the values of other registers in addition to the stack pointer and program counter. Consequently: the values of automatic variables are unspecified after a call to longjmp() if they meet all of the following criteria:

  • they are local to the function that made the corresponding setjmp() call;
  • their values are changed between the calls to setjmp() and longjmp(); and
  • they are not declared as volatile.

Analogous remarks apply for siglongjmp(). so yeah, volatile is your friend here, fr fr ๐Ÿ˜ญ

๐ŸŒ€ Nonlocal gotos and program readability ๐ŸŒ€

While it can be abused, the traditional C goto statement at least has the benefit that lexical cues (the goto statement and the target label) let the programmer easily perceive the flow of control. Nonlocal gotos provide no such cues: multiple setjmp() calls might employ the same jmp_buf variable, so the content of that variable may change over the lifetime of the application. ๐Ÿ˜ต๐Ÿ’ซ

Consequently, the programmer may be forced to do a detailed reading of the code just to figure out the dynamic target of a particular longjmp() call. (To make the programmer's life easier, each setjmp() call should employ a unique jmp_buf variable.) ๐Ÿท๏ธ

Adding further difficulty: the setjmp() and longjmp() calls may not even be in the same source code module. ๐Ÿ™ˆ

In summary โ€” nonlocal gotos can make programs harder to understand and maintain, and an alternative should be used if possible. that's not me being dramatic, that's the manpage ๐Ÿ’…

๐ŸŒช๏ธ Undefined behavior ๐ŸŒช๏ธ

๐Ÿšจ If the function which called setjmp() returns before longjmp() is called, the behavior is undefined. Some kind of subtle or unsubtle chaos is sure to result. genuinely. chaos. ๐Ÿ’€
๐Ÿšจ If, in a multithreaded program, a longjmp() call employs an env buffer that was initialized by a call to setjmp() in a different thread, the behavior is undefined. ๐ŸงตโŒ

POSIX.1-2008 Technical Corrigendum 2 adds longjmp() and siglongjmp() to the list of async-signal-safe functions. However, the standard recommends avoiding the use of these functions from signal handlers ๐Ÿ‘€ and goes on to point out that if these functions are called from a signal handler that interrupted a call to a non-async-signal-safe function (or some equivalent, such as the steps equivalent to exit(3) that occur upon a return from the initial call to main()), the behavior is undefined if the program subsequently makes a call to a non-async-signal-safe function.

The only way of avoiding undefined behavior is to ensure one of the following:

  • After long jumping from the signal handler, the program does not call any non-async-signal-safe functions and does not return from the initial call to main().
  • Any signal whose handler performs a long jump must be blocked during every call to a non-async-signal-safe function and no non-async-signal-safe functions are called after returning from the initial call to main().

๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹


and that's the page, bestie!! this one's from Linux man-pages 6.20, dated 2026-02-08 โ€” go forth and nonlocal-goto responsibly ๐Ÿ‘‘โœจ๐Ÿ’–

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: GPL-2.0-or-later
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms