This rework was motivated by the non-stop mode. To handle stepping over longjmp, currently, we create internal disabled breakpoints on everything that looks like a longjmp : "longjmp", "_longjmp", "siglongjmp", and "_siglongjmp". These should cover all cases and all OSs. The basic idea it that when one of these breakpoints is hit, we look into the jmp_buf passed into longjmp, and extract the destination PC from it. We then set a breakpoint at that address, and let the inferior hit it. This handling is only desirable when the user is activelly doing a next or a step. We don't care for the inferior hitting a longjmp when the inferior is running freely -- if we left the breakpoint enabled all the time, even when not stepping (e.g., user did a continue, and no user breakpoints were hit, the inferior just runs uninterrupted), anytime the inferior called longjmp, it would hit the breakpoint, and then gdb would notice the inferior was not being stepped, so it should be resumed immediately. It is much more efficient to not hit that breakpoint at all in that case. So far, so good, this works OK in all-stop mode. Well, in theory, because the current implementation is broken. However, in non-stop mode, we can step more than one thread independenly and simultaneously. Having one thread finish a step, and disable the global longjmp breakpoint at that point, while another thread is still stepping is definitelly wrong. The other thread may happen to step a longjmp and it would go unnoticed. Basically, we need to associate the longjmp breakpoints with each stepping thread. Fortunally, the concept of per-thread breakpoints already exists in GDB. The current implementation sets a handling_longjmp variable when a longjmp is hit, and we insert a longjmp-resume breakpoint. If you look at infrun.c, you'll see there's always a FIXME associated with it. And it's right, because it's handling is broken. You can easilly see it breaking, by trying to step over something like this: #include jmp_buf env; int call_longjmp (jmp_buf *buf) { longjmp (*buf, 1); } int main () { if (setjmp (env) == 0) /* patt2 */ { call_longjmp (&env); <<<<<<<< try to step over this. } else { printf ("resumed\n"); } } Basically, the symptom is that GDB will not stop at the longjmp-resume address, instead the inferior will run to exit. Quite annoying. Instead of trying to explain deeply why the current implementation is broken (has to do with bad breakpoint handling, thread hopping, removing breakpoints at the wrong time, and the handling_longjmp variable getting in the way), I propose another implementation. We get rid of handling_longjmp, and instead, we handle a longjmp-resume breakpoint much like a step-resume breakpoint. It's natural to not have both set at the same time, and the current code already gets rid of the active step-resume breakpoint when inserting the longjmp-resume breakpoint. Setting step_resume_breakpoint to the new longjmp-resume breakpoint is exactly what we want. We want to keep stepping while it is set, we want to context switch it. We want to delete it everywhere a step-resume is being deleted. Of course, we could have a seperate per-thread context-switchable longjmp_resume_breakpoint instead, since we never have both a longjmp-resume and a step-resume breakpoint simulatenously (in a given thread), and it's handling would be equal everywhere else, it just feels better to overload step_resume_breakpoint. This patch implements the same behaviour that's in HEAD (if it weren't broken a lot of the times) where any longjmp hit while stepping, causes the step to stop. -- Pedro Alves P.S.: However, we could extend this to be smarter. E.g.: void hidden_longjmp (void) { if (setjmp (env) == 0) { longjmp (env, 1); } else { printf ("resumed\n"); } } int main () { hidden_longjmp (); <<<< step over this. } The longjmp inside hidden_longjmp is going to land inside hidden_longjmp. GDB could ignore it leave the step-resume breakpoint at the return of hidden_longjmp and pretend that longjmp was never seen. Think of stepping over a function in gdb's sources, and an exception being thrown and caught all somewhere inner to the function you're stepping. I've implemented a prototype patch that does this. Does anyone else think that behaviour is useful? (I'm aware that any smartness we add can be defeated by longjmp changing stacks, or stuff like debugging coroutines implemented with set/longjmp, but those feel like rare enough that a smart mode could be the default and useful most of (almost-all) the times.)