From owner-freebsd-bugs Thu Dec 27 16: 2: 9 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id B2EA237B419 for ; Thu, 27 Dec 2001 16:00:10 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id fBS00AV96718; Thu, 27 Dec 2001 16:00:10 -0800 (PST) (envelope-from gnats) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id F0E2237B417 for ; Thu, 27 Dec 2001 15:54:41 -0800 (PST) Received: (from nobody@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id fBRNsf696158; Thu, 27 Dec 2001 15:54:41 -0800 (PST) (envelope-from nobody) Message-Id: <200112272354.fBRNsf696158@freefall.freebsd.org> Date: Thu, 27 Dec 2001 15:54:41 -0800 (PST) From: Kip Macy To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: gnu/33262: gdb does not handle pending signals correctly when single stepping Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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 #include /* for implementing system tic */ #include #include #include 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 , 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 , 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 , 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 , 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 , 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 , 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