From mboxrd@z Thu Jan 1 00:00:00 1970 From: Guy Harris To: gdb@sourceware.cygnus.com Subject: On Digital UNIX, "continue" doesn't continue correctly if a signal isdelivered Date: Tue, 23 May 2000 21:22:00 -0000 Message-id: <200005240422.VAA19399@tooting> X-SW-Source: 2000-05/msg00120.html On Digital UNIX/Alpha, we have a program that has an interval timer set up to continuously deliver signals; with GDB 4.18, we find that if you stop at a breakpoint, and then try to continue from that breakpoint, it doesn't continue - instead, it stops again at the same breakpoint. The same thing happens with the GDB that was in the CVS tree as of a short while ago. The problem appears to be that various tests in "wait_for_inferior()", which test whether the current SP is for a frame closer to the top of the stack than the frame for "step_sp" (or "step_sp - 16") fail, because "step_sp" hasn't been set. When continuing from the breakpoint (with the PRSTEP flag set in the "pr_flags" field of the structure passed to PIOCRUN, so that it executes only one instruction), it stops in "__sigtramp", as a SIGALRM was delivered to the process in the interval since the breakpoint trap; however, GDB doesn't realize that it's in the signal trampoline, and doesn't properly continue, so that when it next gets a breakpoint trap after returning from the signal, as it presumably re-executes the breakpoint instruction, it doesn't realize that it should drive on, and it just stops. "step_sp" gets set by "step_1()", "step_once()", and "until_next_command()", presumably because all those routines call "proceed()" with "step" set; however, "step_sp" isn't set by "continue_command()" or any routine between "continue_command()" and "proceed()", presumably because "proceed()" isn't called with "step" set in that code path. However, "proceed()" will be single-stepping, because we're resuming from a breakpoint, and we need to step over the instruction at which the breakpoint was placed and then put the breakpoint back, as per: if (addr == (CORE_ADDR) -1) { /* If there is a breakpoint at the address we will resume at, step one instruction before inserting breakpoints so that we do not stop right away (and report a second hit at this breakpoint). */ if (read_pc () == stop_pc && breakpoint_here_p (read_pc ())) oneproc = 1; in "proceed()". Making "proceed()" set "step_frame_address" and "step_sp" if "oneproc" is set but "step" isn't set appears to fix the problem: Index: gdb/infrun.c =================================================================== RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.14 diff -c -r1.14 gdb/infrun.c *** gdb/infrun.c 2000/05/22 09:02:23 1.14 --- gdb/infrun.c 2000/05/24 03:44:38 *************** *** 1040,1048 **** #endif /* HP_OS_BUG */ if (oneproc) ! /* We will get a trace trap after one instruction. ! Continue it automatically and insert breakpoints then. */ ! trap_expected = 1; else { int temp = insert_breakpoints (); --- 1040,1058 ---- #endif /* HP_OS_BUG */ if (oneproc) ! { ! /* We will get a trace trap after one instruction. ! Continue it automatically and insert breakpoints then. */ ! trap_expected = 1; ! ! /* Oh, and if we weren't explicitly told to single-step, our ! caller may not have updated "step_sp", so do it ourselves. */ ! if (!step) ! { ! step_frame_address = FRAME_FP (get_current_frame ()); ! step_sp = read_sp (); ! } ! } else { int temp = insert_breakpoints (); Whether this is the right way to fix this is another matter. (For example, perhaps "proceed()" should always set "step_frame_address" and "step_sp" if it will be passing a non-zero value as the first argument to "resume()", and the routines in "gdb/infcmd.c" that set them should leave it up to "proceed()" to do so.) I've attached a small sample program which exhibits the problem; if run with "clock" as an argument, it sets up a timer to repeatedly deliver SIGALRM, and if you set a breakpoint on "procedure()", run the program, and then type "continue", it will stop again in "procedure()" without printing "Hello", indicating that it hasn't continued from the breakpoint. However, if run with "noclock" as an argument, so that it doesn't repeatedly get SIGALRM, it *will* print "Hello" before stopping again at "procedure()". Applying the patch above makes "continue" behave correctly regardless of whether the program was run with "clock" or "noclock".