16

I'm a C++ programmer and used to OO languages with good exception handling.

From what I can understand, setjmp and longjmp are essentially a c-style way to propogate exception conditions. They also seem like an intense form of goto that can propogate up the stack.

So, first of all: Is it good practice to use these in straight up C as of this point in time, or are they deprecated? (note: C not C++).

Secondly, do they have any use in C++ or am I correct in thinking they were a legacy mechanism which was replaced by exception handling features of C++?

Puppy
  • 144,682
  • 38
  • 256
  • 465
John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • 5
    You can't throw an exception in a signal handler, but you can do a `longjmp` safely -- as long as you know what you are doing. – Dietrich Epp Aug 31 '11 at 19:57
  • 2
    @Dietrich: +1 to your comment. This is a little-known and completely-under-appreciated fact. There are a number of problems that **cannot** be solved (nasty race conditions) without using `longjmp` out of signal handlers. Asynchronous interruption of blocking syscalls is the classic example. – R.. GitHub STOP HELPING ICE Sep 01 '11 at 05:30

7 Answers7

7

Essentially, you're right in your assertion that jmp-style propagation is essentially the same thing as goto. Read Dijkstra's (famous and controversial) paper about gotos which (I think) provides sensible reasoning for why gotos should rarely be used. Unless you know exactly why you're doing what you're doing (or you're working in very specific fields -- such as embedded programming), you should not touch either goto or longjmp.

David Titarenco
  • 32,662
  • 13
  • 66
  • 111
  • 5
    +1 for the "Unless you know exactly why you're doing what you're doing". The only time I've had to use `setjmp/longjmp` was when using the libpng library -- when libpng encounters an error in decoding a PNG file, it expects to `longjmp` back to your code, so you have to call `setjmp` properly in order to use it. – Adam Rosenfield Aug 31 '11 at 19:53
  • 3
    Wow, that seems like a really silly design. Instead it could have been written to `longjmp` back to the entry point in libpng itself and simply return an error code to the caller... – R.. GitHub STOP HELPING ICE Sep 01 '11 at 05:24
  • 1
    One thing to aware of, which I consider to be probably the most obscure point in all of C: if a function sets a local var, then calls setjmp, then changes that var, then calls a function which longjmps back to the setjmp, then that local var may, or may not, be restored to its value at the time of the setjmp. Basically it depends on whether the value was in a callee-saved reg at the setjmp. (and 'most obscure part of C', since setjmp is not entirely a lib function, compilers generally need to recognize it when generating code for the function that calls it). – greggo Apr 13 '12 at 21:19
  • 4
    @greggo that's why the standard prescribes to use volatile variables in this case, thus avoiding the undefined behaviour you describe. – Fabio Pozzi Feb 26 '13 at 11:43
6

they are used to implement coroutines. There are a couple of c++ coroutine libraries running around on the net, that in Unix/Linux will use setjmp/longjmp to implement the functionality.

So, if your goal is to implement a coroutine library, then it is a moot point if its good practice or not, since on those platforms it is the only way to support that functionality.

if your goal is to use a coroutine library, you should search for some of these instead. There is even a boost vault proposal called boost::context, which is already approved.

lurscher
  • 25,930
  • 29
  • 122
  • 185
  • Coroutine libraries on POSIX systems probably use `set_context/make_context` instead, since you can't maintain multiple stacks with `setjmp/longjmp`. – Alexandre C. Aug 31 '11 at 20:03
  • @Alexandre C. you probably mean `setcontext` and `makecontext`. These are declared obsolete. – Jens Gustedt Aug 31 '11 at 20:38
  • @Jens: yes. Are they ? I remember having used them to implement coroutines, since `makecontext` can be used to call a function with a custom stack. In favor of what would they be deprecated ? – Alexandre C. Aug 31 '11 at 20:44
  • @Jens: Oh, I see, (http://stackoverflow.com/questions/4298986/is-there-something-to-replace-the-ucontext-h-functions ). I don't see any problem with using them. – Alexandre C. Aug 31 '11 at 20:46
  • 2
    @R.: they solve quite different problems than threads solve. If I want a bunch of small stacks with functions yielding to each other in predictable ways (say generators/consumers, or tree algorithms like same fringe), then I want coroutines, not threads. – Alexandre C. Sep 01 '11 at 09:51
4

There are some correct uses of setjmp/longjmp. Implementing coroutines with them is virtually impossible, since you have to use (nonportable) tricks (read: inline assembly) to switch stacks.

One use of setjmp/longjmp is to catch floating point signals, but this messes up the C++ stack unwinding. Correct in C though.

You can also implement some form of stack unwinding (by maintaining you own cleanup handler stack) and implement true destructors and exceptions in C with them. This is very handy in large projects: the lack of a correct error handling mechanism is the weak point of C. However, it is quite difficult to do it correctly, and you'll have to write a bunch of macros to facilitate the task.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • Actually you can switch stacks without inline assembly, using `sigaltstack`, `sigaction`, and `raise`. :-) – R.. GitHub STOP HELPING ICE Sep 01 '11 at 05:26
  • That is probably slow though, and the amount needed of inline assembly needed is not very large. You should be able to create different asm for each processor you target. – Demi Sep 07 '13 at 00:59
3

You should have brought up the issue that goto and maybe longjmp are not good before Exception handling (Try+catch+finally+..) became popular (using longjmp). If people can't handle a sparse usage of goto to make things easier then how can they handle all of the permutations of logic bypassed by the longjmp exception handling and then continue on like nothing happened? The real issue is people are looking for rules instead of concepts.

2

You certainly don't want to use setjmp in C++, as you say that's what exceptions are for. You don't want to use them in C either because it's exceedingly hard to get right. Try very hard to find other solutions.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

setjmp/longjmp is a useful way to implement an own exception-handling in pure C. http://sourceware.org/pthreads-win32/announcement.html

user411313
  • 3,930
  • 19
  • 16
0

setjmp and longjmp are macros used to bypass normal function call and return flow.
The setjmp saves the calling env to be used by longjmp
Use of these macros correctly is really hard and you can easily end up with undefined behavior.
Because of this, it is mandated for example to restrict longjmp to 1 level of signal handler (best actually to not be called at all).
In critical systems it is required not to be used at all.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • Where is `longjmp` restricted to one level of signal handler? `longjmp` is async-signal-unsafe, so you can't call it from a signal handler if the interrupted code (in the main context or in a previously-invoked signal handler context) might be using an async-signal-unsafe function, but otherwise I know of no such restriction. – R.. GitHub STOP HELPING ICE Sep 01 '11 at 05:28
  • I remember reading somewhere connected to the official standard that the restriction on longjmp is an error and will be removed. – Demi Sep 07 '13 at 01:02