Date: Thu, 27 Dec 2001 15:54:41 -0800 (PST) From: Kip Macy <kip_macy@yahoo.com> To: freebsd-gnats-submit@FreeBSD.org Subject: gnu/33262: gdb does not handle pending signals correctly when single stepping Message-ID: <200112272354.fBRNsf696158@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 33262 >Category: gnu >Synopsis: gdb does not handle pending signals correctly when single stepping >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Dec 27 16:00:10 PST 2001 >Closed-Date: >Last-Modified: >Originator: Kip Macy >Release: 4.4 >Organization: Extended Solutions >Environment: FreeBSD raidclient1.lab.netapp.com 4.4-STABLE FreeBSD 4.4-STABLE #1: Tue Oct 23 22:43:28 PDT 2001 kmacy@raidclient1.lab.netapp.com:/usr/src/sys/compile/DEVELOPMENT i386 >Description: when a signal is pending (e.g. SIGALRM) at a breakpoint and the user tries to single step - gdb will break at the signal handler in non-thread-code and at _sys_thread_sigprocmask in threaded code. This makes it impossible to step through code that makes heavy use of signals. This is an example of the behaviour: > gdb alr^Gmtest^M GNU gdb 4.18 Copyright 1998 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 "i386-unknown-freebsd"... (gdb) b main Breakpoint 1 at 0x8048666: file alrmtest.c, line 44. (gdb) r Starting program: /amd/ayr/vol/users2/home/kmacy/alrmtest Breakpoint 1, main () at alrmtest.c:44 44 sk_init_timer(); (gdb) n 45 while (1) { (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. 0x80485c0 in sk_millisecond_clock () at alrmtest.c:10 10 sk_millisecond_clock() (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. main () at alrmtest.c:45 45 while (1) { (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. 0x80485c0 in sk_millisecond_clock () at alrmtest.c:10 10 sk_millisecond_clock() (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. main () at alrmtest.c:45 45 while (1) { (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. 0x80485c0 in sk_millisecond_clock () at alrmtest.c:10 10 sk_millisecond_clock() (gdb) n Program received signal SIGTRAP, Trace/breakpoint trap. main () at alrmtest.c:45 45 while (1) { This is the correct behavior (same program on Linux or Solaris): [kmacy@pris ~]$ gdb linux_alrmtest/alrmtest GNU gdb 5.0 Copyright 2000 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 "i686-pc-linux-gnu"... (gdb) bt No stack. (gdb) b main Breakpoint 1 at 0x804857e: file alrmtest.c, line 44. (gdb) r Starting program: /n/ayr/users2/kmacy/linux_alrmtest/alrmtest Breakpoint 1, main () at alrmtest.c:44 44 sk_init_timer(); (gdb) n 45 while (1) { (gdb) n 50 i = 0; (gdb) n 54 j = 0; (gdb) n 55 printf("milliseconds elapsed is %d\n", sk_msecs4); (gdb) n milliseconds elapsed is 40 56 tmp_sleep(2); (gdb) n 57 } (gdb) n 45 while (1) { (gdb) n 50 i = 0; (gdb) n 54 j = 0; (gdb) n 55 printf("milliseconds elapsed is %d\n", sk_msecs4); (gdb) n milliseconds elapsed is 110 56 tmp_sleep(2); (gdb) n 57 } (gdb) q >How-To-Repeat: single step through the while loop in alrmtest, the code follows: #include <sys/types.h> #include <sys/time.h> /* for implementing system tic */ #include <signal.h> #include <stdio.h> #include <setjmp.h> int sk_msecs4; #define SK_MSEC_PER_TIC 10 void sk_millisecond_clock() { extern int sk_msecs4; sk_msecs4 += SK_MSEC_PER_TIC; } /* */ void sk_init_timer() { struct itimerval tic; struct sigaction action; action.sa_handler = (void*) sk_millisecond_clock; action.sa_flags = SA_RESTART; sigemptyset(&action.sa_mask); sigaction(SIGALRM, &action, NULL); tic.it_interval.tv_sec = 0; tic.it_interval.tv_usec = SK_MSEC_PER_TIC * 1000; tic.it_value = tic.it_interval; setitimer(ITIMER_REAL, &tic, NULL); } unsigned int tmp_sleep(unsigned int seconds) { struct timeval t; t.tv_sec = seconds; t.tv_usec = 0; select(0, NULL, NULL, NULL, &t); } int main() { int i, j; sk_init_timer(); while (1) { /* useless assignment to demonstrate lack of * progress */ i = 0; /* useless assignment to demonstrate lack of * progress */ j = 0; printf("milliseconds elapsed is %d\n", sk_msecs4); tmp_sleep(2); } } >Fix: Not sure yet, but the following indicates to me that freebsd_uthread_wait is not correct: Breakpoint 6, wait_for_inferior () at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/infrun.c:1064 1064 registers_changed (); (gdb) p w $19 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0xe, sig = TARGET_SIGNAL_ALRM, related_pid = 0xe, execd_pathname = 0xe <Error reading address 0xe: Bad address>, syscall_id = 0xe } } (gdb) n 1066 if (target_wait_hook) (gdb) p w $20 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0xe, sig = TARGET_SIGNAL_ALRM, related_pid = 0xe, execd_pathname = 0xe <Error reading address 0xe: Bad address>, syscall_id = 0xe } } (gdb) n 1069 pid = target_wait (-1, &w); (gdb) p w $21 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0xe, sig = TARGET_SIGNAL_ALRM, related_pid = 0xe, execd_pathname = 0xe <Error reading address 0xe: Bad address>, syscall_id = 0xe } } (gdb) n 1074 thread_step_needed = 0; (gdb) p w $22 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0x5, sig = TARGET_SIGNAL_TRAP, related_pid = 0x5, execd_pathname = 0x5 <Error reading address 0x5: Bad address>, syscall_id = 0x5 } } (gdb) p hoststatus $50 = 0x57f (gdb) p *ourstatus $51 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0xe, sig = TARGET_SIGNAL_ALRM, related_pid = 0xe, execd_pathname = 0xe <Error reading address 0xe: Bad address>, syscall_id = 0xe } } (gdb) s target_signal_from_host (hostsig=0x5) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/target.c:1307 1307 { (gdb) list 1302 1303 /* Convert host signal to our signals. */ 1304 enum target_signal 1305 target_signal_from_host (hostsig) 1306 int hostsig; 1307 { 1308 /* A switch statement would make sense but would require special kludges 1309 to deal with the cases where more than one signal has the same number. */ 1310 1311 if (hostsig == 0) return TARGET_SIGNAL_0; (gdb) p hostsig $52 = 0x5 (gdb) bt #0 target_signal_from_host (hostsig=0x5) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/target.c:1307 #1 0x80b9abb in store_waitstatus (ourstatus=0xbfbff538, hoststatus=0x57f) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/target.c:1690 #2 0x808a268 in child_wait (pid=0xffffffff, ourstatus=0xbfbff538) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/inftarg.c:247 #3 0x8080d60 in freebsd_uthread_wait (pid=0xffffffff, ourstatus=0xbfbff538) at /usr/src/gnu/usr.bin/binutils/gdb/freebsd-uthread.c:511 #4 0x8087bb4 in wait_for_inferior () at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/infrun.c:1069 #5 0x8087a09 in proceed (addr=0xffffffff, siggnal=TARGET_SIGNAL_DEFAULT, step=0x1) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/infrun.c:922 #6 0x8085446 in step_1 (skip_subroutines=0x1, single_inst=0x0, count_string=0x0) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/infcmd.c:416 #7 0x80852b1 in next_command (count_string=0x0, from_tty=0x1) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/infcmd.c:332 #8 0x80bc317 in execute_command (p=0x8186001 "", from_tty=0x1) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/top.c:1268 #9 0x80bc4a9 in command_loop () at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/top.c:1365 #10 0x8093665 in main (argc=0x1, argv=0xbfbff7ec) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/main.c:636 #11 0x804a52d in _start (arguments=0xbfbff8f4 "/usr/libexec/elf/gdb") at /usr/src/lib/csu/i386-elf/crt1.c:96 (gdb) up #1 0x80b9abb in store_waitstatus (ourstatus=0xbfbff538, hoststatus=0x57f) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/target.c:1690 1690 ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus)); (gdb) finish Run till exit from #1 0x80b9abb in store_waitstatus (ourstatus=0xbfbff538, hoststatus=0x57f) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/target.c:1690 child_wait (pid=0xffffffff, ourstatus=0xbfbff538) at /usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/inftarg.c:248 248 return pid; (gdb) list 243 /* hack for thread testing */ 244 } while( (pid != inferior_pid) && not_same_real_pid ); 245 /*##*/ 246 247 store_waitstatus (ourstatus, status); 248 return pid; 249 } 250 #endif /* CHILD_WAIT */ 251 252 #if !defined(CHILD_POST_WAIT) (gdb) p *ourstatus $53 = { kind = TARGET_WAITKIND_STOPPED, value = { integer = 0x5, sig = TARGET_SIGNAL_TRAP, related_pid = 0x5, execd_pathname = 0x5 <Error reading address 0x5: Bad address>, syscall_id = 0x5 } } (gdb) >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200112272354.fBRNsf696158>