This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix problem on solaris with single stepping and signal handling


There is a problem on Solaris with signals that are being caught by
gdb and not passed on to the inferior.  It can be reproduced as
follows:

(1) Set a breakpoint and run the program until gdb stops at the
breakpoint

(2) Send the stopped process a signal like SIGALRM

(3) Try to single step the stopped process

(4) The process either will remain at the breakpoint or run freely to
the next breakpoint and/or exit.  I've seen both behaviors.

The problem is that gdb is unnecessarily setting a step resume
breakpoint for signals that are not going to be passed to the
inferior.  Then in a later pass through handle_inferior_event, the
presence of this breakpoint, after the inferior has stepped off the
breakpoint, allows the inferior to free run instead of stopping (for
the free run case), which makes sense if you want it to run the signal
handler and then break when it returns to the location of the step
resume breakpoint.  What actually happens of course is that gdb simply
steps off the breakpoint and then free runs the code it would have
executed in the absence of the signal.

Below is an example of how to reproduce the problem, and a simple
patch.  "gdb-old" is the version before the patch and "gdb" is the
version after the patch.

============================================================================

$ cat sigtest.c
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

int ppid;
int cpid;

void bar ()
{
}

main ()
{
  ppid = getpid ();
  cpid = fork ();
  if (cpid > 0)
    for (;;)
      {
        bar ();
        sleep (1);
      }
  else
    for (;;)
      {
        kill (ppid, SIGALRM);
        sleep (1);
      }
}


$ gcc -g -o sigtest sigtest.c


$ ./gdb-old sigtest
GNU gdb 6.5.50.20060923-cvs
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Function "info_command" not defined.
/home/fnf/sandbox/experimental/build/sparc-sun-solaris2.8/gdb/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) handle SIGALRM nopass
Signal        Stop      Print   Pass to program Description
SIGALRM       No        No      No              Alarm clock
(gdb) br bar
Breakpoint 1 at 0x105a4: file sigtest.c, line 10.
(gdb) run
Starting program: /home/fnf/sandbox/experimental/build/sparc-sun-solaris2.8/gdb/gdb/sigtest 

Breakpoint 1, bar () at sigtest.c:10
10      }
(gdb) display/i $pc
1: x/i $pc  0x105a4 <bar+4>:    rett  %i7 + 8
(gdb) stepi
^C   (fnf: inferior is stuck, interrupt it)
Program received signal SIGINT, Interrupt.
0xff31b784 in _sigsuspend () from /usr/lib/libc.so.1
1: x/i $pc  0xff31b784 <_sigsuspend+4>: ta  8
(gdb) quit
The program is running.  Exit anyway? (y or n) y


$ ./gdb sigtest
GNU gdb 6.5.50.20060923-cvs
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Function "info_command" not defined.
/home/fnf/sandbox/experimental/build/sparc-sun-solaris2.8/gdb/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) handle SIGALRM nopass
Signal        Stop      Print   Pass to program Description
SIGALRM       No        No      No              Alarm clock
(gdb) br bar
Breakpoint 1 at 0x105a4: file sigtest.c, line 10.
(gdb) run
Starting program: /home/fnf/sandbox/experimental/build/sparc-sun-solaris2.8/gdb/gdb/sigtest 

Breakpoint 1, bar () at sigtest.c:10
10      }
(gdb) display/i $pc
1: x/i $pc  0x105a4 <bar+4>:    rett  %i7 + 8
(gdb) stepi
0x000105a8 in bar () at sigtest.c:10
10      }
1: x/i $pc  0x105a8 <bar+8>:    nop 
(gdb) 
main () at sigtest.c:20
20              sleep (1);
1: x/i $pc  0x10604 <main+88>:  mov  1, %o0     ! 0x1
(gdb) 
0x00010608      20              sleep (1);
1: x/i $pc  0x10608 <main+92>:  call  0x2081c <sleep@plt>
(gdb) 
0x0001060c      20              sleep (1);
1: x/i $pc  0x1060c <main+96>:  nop 
(gdb) 
0x0002081c in sleep@plt ()
1: x/i $pc  0x2081c <sleep@plt>:        sethi  %hi(0x15000), %g1
(gdb) quit
The program is running.  Exit anyway? (y or n) y
$ exit
exit

============================================================================

2007-01-25  Fred Fish  <fnf@specifix.com>

	* infrun.c (handle_inferior_event): Don't set a step resume
	breakpoint for signals that are not being passed on to the
	inferior.

Index: infrun.c
diff -u -p -r1.1.1.5.2.4 infrun.c
--- infrun.c	25 Sep 2006 02:04:52 -0000	1.1.1.5.2.4
+++ infrun.c	25 Jan 2007 17:20:13 -0000
@@ -1964,6 +1964,7 @@ process_event_stop_test:
 	stop_signal = TARGET_SIGNAL_0;
 
       if (prev_pc == read_pc ()
+	  && stop_signal != TARGET_SIGNAL_0
 	  && !breakpoints_inserted
 	  && breakpoint_here_p (read_pc ())
 	  && step_resume_breakpoint == NULL)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]