[[!meta copyright="Copyright © 2013 Free Software Foundation, Inc."]] [[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable id="license" text="Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled [[GNU Free Documentation License|/fdl]]."]]"""]] [[!tag open_issue_gdb open_issue_glibc]] # IRC, freenode, #hurd, 2013-07-07 Hi, I'm in GDB inside a handler for SIGHUP, after stepping out, gdb will hang on instruction: <_hurd_sigstate_lock+88>: xchg %edx,0x4(%eax) here is my signal test pasted: http://pastebin.com/U72qw3FC #include #include #include void * my_handler(int signal, void *info, void *context) { printf("got SIGHUP\n"); return NULL; } void install_handler (int signal) { struct sigaction sa; sa.sa_sigaction = my_handler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(signal, &sa, NULL); } void test_sighup(void) { raise(SIGHUP); } int main(int argc, char **argv){ install_handler(SIGHUP); test_sighup(); exit(1); } zyg: thanks zyg: what is the problem exactly ? zyg: i mean, does it hand before attaching with gdb ? braunr: it doesn't hang if runned without gdb. I've pasted here when I step out of the handler, and get to the hanging instruction: http://pastebin.com/nUyCx6Wj $ gdb --args a.out GNU gdb (GDB) 7.6-debian Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-gnu". For bug reporting instructions, please see: ... Reading symbols from /home/shrek/a.out...(no debugging symbols found)...done. (gdb) (gdb) display/i $pc (gdb) handle SIGHUP pass stop print Signal Stop Print Pass to program Description SIGHUP Yes Yes Yes Hangup (gdb) (gdb) run Starting program: /home/shrek/a.out [New Thread 3571.5] Program received signal SIGHUP, Hangup. 0x010548ec in mach_msg_trap () at /build/buildd-eglibc_2.17-6-hurd-i386-g946kE/eglibc-2.17/build-tree/hurd-i386-libc/mach/mach_msg_trap.S:2 2 /build/buildd-eglibc_2.17-6-hurd-i386-g946kE/eglibc-2.17/build-tree/hurd-i386-libc/mach/mach_msg_trap.S: No such file or directory. 1: x/i $pc => 0x10548ec : ret (gdb) (gdb) si 0x0804862d in my_handler () 1: x/i $pc => 0x804862d : push %ebp (gdb) x/20xi 0x804862d => 0x804862d : push %ebp 0x804862e : mov %esp,%ebp 0x8048630 : sub $0x18,%esp 0x8048633 : movl $0x8048750,(%esp) 0x804863a : call 0x8048500 0x804863f : mov $0x0,%eax 0x8048644 : leave 0x8048645 : ret 0x8048646 : push %ebp 0x8048647 : mov %esp,%ebp 0x8048649 : sub $0x28,%esp 0x804864c : movl $0x804862d,-0x14(%ebp) 0x8048653 : movl $0x40,-0xc(%ebp) 0x804865a : lea -0x14(%ebp),%eax 0x804865d : add $0x4,%eax 0x8048660 : mov %eax,(%esp) 0x8048663 : call 0x80484d0 0x8048668 : movl $0x0,0x8(%esp) 0x8048670 : lea -0x14(%ebp),%eax 0x8048673 : mov %eax,0x4(%esp) (gdb) (gdb) break *0x804863f Breakpoint 1 at 0x804863f (gdb) c Continuing. got SIGHUP Breakpoint 1, 0x0804863f in my_handler () 1: x/i $pc => 0x804863f : mov $0x0,%eax (gdb) (gdb) si 0x08048644 in my_handler () 1: x/i $pc => 0x8048644 : leave (gdb) 0x08048645 in my_handler () 1: x/i $pc => 0x8048645 : ret (gdb) 0x010708b2 in trampoline () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x10708b2 : add $0xc,%esp (gdb) 0x010708b5 in trampoline () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x10708b5 : ret (gdb) __sigreturn (scp=0x102988c) at ../sysdeps/mach/hurd/i386/sigreturn.c:30 30 ../sysdeps/mach/hurd/i386/sigreturn.c: No such file or directory. 1: x/i $pc => 0x1096340 <__sigreturn>: push %ebp (gdb) 0x01096341 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096341 <__sigreturn+1>: push %edi (gdb) 0x01096342 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096342 <__sigreturn+2>: push %esi (gdb) 0x01096343 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096343 <__sigreturn+3>: push %ebx (gdb) 0x01096344 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096344 <__sigreturn+4>: sub $0x2c,%esp (gdb) 0x01096347 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096347 <__sigreturn+7>: mov 0x40(%esp),%esi (gdb) 0x0109634b 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x109634b <__sigreturn+11>: call 0x11a0609 <__x86.get_pc_thunk.bx> (gdb) 0x011a0609 in __x86.get_pc_thunk.bx () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x11a0609 <__x86.get_pc_thunk.bx>: mov (%esp),%ebx (gdb) 0x011a060c in __x86.get_pc_thunk.bx () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x11a060c <__x86.get_pc_thunk.bx+3>: ret (gdb) 0x01096350 in __sigreturn (scp=0x102988c) at ../sysdeps/mach/hurd/i386/sigreturn.c:30 30 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096350 <__sigreturn+16>: add $0x15ccb0,%ebx (gdb) 35 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096356 <__sigreturn+22>: test %esi,%esi (gdb) 0x01096358 35 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096358 <__sigreturn+24>: je 0x10964f0 <__sigreturn+432> (gdb) 0x0109635e 35 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x109635e <__sigreturn+30>: testl $0x10100,0x4(%esi) (gdb) 0x01096365 35 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x1096365 <__sigreturn+37>: jne 0x10964f0 <__sigreturn+432> (gdb) __hurd_threadvar_location_from_sp (__sp=, __index=) at ../hurd/hurd/threadvar.h:94 94 ../hurd/hurd/threadvar.h: No such file or directory. 1: x/i $pc => 0x109636b <__sigreturn+43>: mov -0x38(%ebx),%ebp (gdb) __hurd_threadvar_location (__index=_HURD_THREADVAR_SIGSTATE) at ../hurd/hurd/threadvar.h:116 116 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x1096371 <__sigreturn+49>: mov %esp,%edx (gdb) __hurd_threadvar_location_from_sp (__sp=0x1029848, __index=_HURD_THREADVAR_SIGSTATE) at ../hurd/hurd/threadvar.h:94 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x1096373 <__sigreturn+51>: cmp 0x0(%ebp),%esp (gdb) 0x01096376 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x1096376 <__sigreturn+54>: jae 0x10964d0 <__sigreturn+400> (gdb) 0x0109637c 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x109637c <__sigreturn+60>: mov -0x15c(%ebx),%eax (gdb) 0x01096382 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x1096382 <__sigreturn+66>: and (%eax),%edx (gdb) 0x01096384 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x1096384 <__sigreturn+68>: mov -0x90(%ebx),%eax (gdb) 0x0109638a 94 in ../hurd/hurd/threadvar.h 1: x/i $pc => 0x109638a <__sigreturn+74>: add (%eax),%edx (gdb) _hurd_self_sigstate () at ../hurd/hurd/signal.h:165 165 ../hurd/hurd/signal.h: No such file or directory. 1: x/i $pc => 0x109638c <__sigreturn+76>: mov 0x8(%edx),%edi (gdb) 0x0109638f 165 in ../hurd/hurd/signal.h 1: x/i $pc => 0x109638f <__sigreturn+79>: test %edi,%edi (gdb) 0x01096391 165 in ../hurd/hurd/signal.h 1: x/i $pc => 0x1096391 <__sigreturn+81>: je 0x1096598 <__sigreturn+600> (gdb) __sigreturn (scp=0x102988c) at ../sysdeps/mach/hurd/i386/sigreturn.c:42 42 ../sysdeps/mach/hurd/i386/sigreturn.c: No such file or directory. 1: x/i $pc => 0x1096397 <__sigreturn+87>: mov %edi,(%esp) (gdb) 0x0109639a 42 in ../sysdeps/mach/hurd/i386/sigreturn.c 1: x/i $pc => 0x109639a <__sigreturn+90>: call 0x1051d70 <_hurd_sigstate_lock@plt> (gdb) 0x01051d70 in _hurd_sigstate_lock@plt () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x1051d70 <_hurd_sigstate_lock@plt>: jmp *0x864(%ebx) (gdb) _hurd_sigstate_lock (ss=ss@entry=0x1244008) at hurdsig.c:170 170 hurdsig.c: No such file or directory. 1: x/i $pc => 0x106bb90 <_hurd_sigstate_lock>: sub $0x1c,%esp (gdb) 0x0106bb93 170 in hurdsig.c 1: x/i $pc => 0x106bb93 <_hurd_sigstate_lock+3>: mov %ebx,0x14(%esp) (gdb) 0x0106bb97 170 in hurdsig.c 1: x/i $pc => 0x106bb97 <_hurd_sigstate_lock+7>: call 0x11a0609 <__x86.get_pc_thunk.bx> (gdb) 0x011a0609 in __x86.get_pc_thunk.bx () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x11a0609 <__x86.get_pc_thunk.bx>: mov (%esp),%ebx (gdb) 0x011a060c in __x86.get_pc_thunk.bx () from /lib/i386-gnu/libc.so.0.3 1: x/i $pc => 0x11a060c <__x86.get_pc_thunk.bx+3>: ret (gdb) 0x0106bb9c in _hurd_sigstate_lock (ss=ss@entry=0x1244008) at hurdsig.c:170 170 in hurdsig.c 1: x/i $pc => 0x106bb9c <_hurd_sigstate_lock+12>: add $0x187464,%ebx (gdb) 0x0106bba2 170 in hurdsig.c 1: x/i $pc => 0x106bba2 <_hurd_sigstate_lock+18>: mov %esi,0x18(%esp) (gdb) 170 in hurdsig.c 1: x/i $pc => 0x106bba6 <_hurd_sigstate_lock+22>: mov 0x20(%esp),%esi (gdb) sigstate_is_global_rcv (ss=0x1244008) at hurdsig.c:162 162 in hurdsig.c 1: x/i $pc => 0x106bbaa <_hurd_sigstate_lock+26>: lea 0x57c0(%ebx),%eax (gdb) 0x0106bbb0 162 in hurdsig.c 1: x/i $pc => 0x106bbb0 <_hurd_sigstate_lock+32>: mov (%eax),%eax (gdb) 163 in hurdsig.c 1: x/i $pc => 0x106bbb2 <_hurd_sigstate_lock+34>: test %eax,%eax (gdb) 0x0106bbb4 163 in hurdsig.c 1: x/i $pc => 0x106bbb4 <_hurd_sigstate_lock+36>: je 0x106bbbc <_hurd_sigstate_lock+44> (gdb) 0x0106bbb6 163 in hurdsig.c 1: x/i $pc => 0x106bbb6 <_hurd_sigstate_lock+38>: cmpl $0x1,0x18(%esi) (gdb) 0x0106bbba 163 in hurdsig.c 1: x/i $pc => 0x106bbba <_hurd_sigstate_lock+42>: je 0x106bbe0 <_hurd_sigstate_lock+80> (gdb) _hurd_sigstate_lock (ss=ss@entry=0x1244008) at hurdsig.c:172 172 in hurdsig.c 1: x/i $pc => 0x106bbe0 <_hurd_sigstate_lock+80>: lea 0x4(%eax),%ecx (gdb) __spin_try_lock (__lock=0x124480c) at ../sysdeps/mach/i386/machine-lock.h:59 59 ../sysdeps/mach/i386/machine-lock.h: No such file or directory. 1: x/i $pc => 0x106bbe3 <_hurd_sigstate_lock+83>: mov $0x1,%edx (gdb) 0x0106bbe8 59 in ../sysdeps/mach/i386/machine-lock.h 1: x/i $pc => 0x106bbe8 <_hurd_sigstate_lock+88>: xchg %edx,0x4(%eax) (gdb) zyg: i don't get what you mean are you starting it with gdb ? braunr: yes: "gdb --args a.out" ok can't reproduce it i get "Program received signal SIGHUP, Hangup. " then continue, then the program has exited braunr: do you run it in gdb or without? braunr: Ah "Program received signal SIGHUP, Hangup." is from gdb.. try issue continue, not sure why gdb stops at SIGHUP (default?). 10:34 < braunr> then continue, then the program has exited gdb stops at signals braunr: yes, try repeating that, but instead of continue, just issue "si" braunr: sorry.. you would need to remove that printf/fprintf, else it gets too long. That's why I put a breakpoint. a breakpoint ? on the signal handler ? braunr: yes, put a break after having entered the handler. Or edit the pasted C code an remove that printf("got SIGHUP\n"); i'm not sure that's correctly supported and i can see why glibc would deadlock on the sigstate lock don't do that :p braunr: why does it deadlock? because both the signal handler and messages from gdb will cause common code paths to be taken braunr: oh.. when I step instruction I'm inside an SIGTRAP handler probably? possible i don't know the details but that's the kind of things i expect and signals on the hurd are definitely buggy i don't know if we support nesting them i'd say we don't braunr: I'll try to put a break beyond that xchg and continue xhcg is probably the sigstate spinlock xchg* you'd need to reach the unlock instruction, which is probably executed once the handler has finished running braunr: yes :) ... one instruction beyond didn't help braunr: thanks alot, putting a break in __sigreturn, after that function has called _hurd_sigstate_unlock@plt works! works ? what did you want to do ? braunr: I want to trace user code inside the signal handler, also how we enter and how we leave. well you can't do that inside, so no it doesn't work for you :/ but that's a start i guess braunr: I seem to do most normal things inside the handler, step-instruction and put breaks. ? i thought that's what made the program deadlock braunr: as you said earlier, the deadlock came when i "step instruction" into the area between _hurd_sigstate_lock and _hurd_sigstate_unlock. Otherwise I havn't had any issues. but isn't the sigstate locked during the handler execution ? braunr: no it locks and unlocks in __sigreturn which is done when leaving the handler. than how could it deadlock on handler entry ? or perhaps the fact your handler was empty made the entry point directly reach __sigreturn hm no i don't buy it the sigstate must also be locked on entry braunr: there was never any problem with entering then describe the problem with more details please ah sorry braunr: are you sure? there is minimal user-code run before the signal is going into the handler. you "step out of the handler" # IRC, freenode, #hurd, 2013-10-24 how come some executables are not debuggable with gdb, e.g Cannot access memory at address xxx. -fPIC flag? no i'm not sure but it's certainly not -fPIC Another example is localedef: ./debian/tmp-libc/usr/bin/localedef -i en_GB -c -f UTF-8 -A /usr/share/locale/locale.alias en_GB.UTF-8 segfailts and in gdb hangs after creating a thread., after C-c no useful info: stack ends with: Cannot access memory at address 0x8382c385 if it's on the stack, it's probably a stack corruption gnu_srs: are u using 'x' command or 'print' in GDB? IIRC print may throw such message, but x may not bt x may too what you're showing looks like an utf-8 string c385 is Å 83 is a special f 82 is a comma so the stack is corrupted:-( probably well, certainly but gdb should show you where the program counter is is that: ECX: the count register no eip program counter == instruction pointer k!, the program counter is at first entry in bt: #0 0x01082612 in _hurd_intr_rpc_msg_in_trap () at intr-msg.c:133 this is the hurd interruptible version of mach_msg so it probably means the corruption was made by a signal handler which is one of the reasons why gdb can't handle Ctrl-c what to do in such a case, follow the source code single-stepping? single stepping also uses signals and using printf will probably create an infinite recursion in those cases, i use mach_print as a first step, you could make sure a signal is actually received and which one hmm also, before rushing into conclusions, make sure you're looking at the right thread i don't expect localedef to be multithreaded but gdb sometimes just doesn't get the thread where the segfault actually occurred two threads: 1095.4 and 1095.5 (created when starting localedef in gdb) no, at the time of the crash the second thread is always the signal thread OK,in gdb the program hangs, interrupted by C-c, outside it segfaults when you use bt to get the corrupted stack, you can also use info threads and thread apply all bt I did: http://paste.debian.net/61170/ ok so it confirms there is only one real application thread, the main one and that the corruption probably occurs during signal handling rpctrace (edited out non-printable characters): http://paste.debian.net/61178/ Ah, have to do it again as root;-) yes .. :p new last part: http://paste.debian.net/61181/ so, there is a seek, then a stat, then a close perhaps (port deallocation) and then a signal received (probably sigsegv) gnu_srs: when you try running it in gdb, do you get a sigkill ? damn, gdb on darnassus is bugged :-( It hangs, interrupted with C-c. ok