This is the mail archive of the gdb-patches@sourceware.cygnus.com 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]

Re: RFA: linux-thread.c change (fixes hang on startup)


> 
> I've done some digging, and it appears that SIGCHLD is *not* blocked
> explicitly by another part of gdb.  (Prior to sending my patch on
> Saturday morning, I looked around for it too, but saw nothing
> obvious.)  After looking a bit harder, I discovered that the process
> signal mask with SIGCHLD blocked is being inherited from the parent.
> 
> Here is what I did to make this determination:
> 
>     1) Debug gdb w/ gdb.  (The choice of the parent gdb is critical.)
>     2) Put a breakpoint on main
>     3) Run 'til the breakpoint on main.
>     4) Determine the pid of the child with "info target"
>     5) cat out /proc/PID/status and observe the mask indicated by
>        SigBlk.
> 
> When I start gdb with an older gdb (gdb-4.17.0.11 which is what installs
> by default on my RH6.0 system), I see no signals blocked.  OTOH, when
> I debug gdb with a recent gdb (the one that I just built myself from
> the development sources), I see:
> 
> 	SigBlk: 0000000000010000
> 
> This indicates that SIGCHLD is blocked.
> 
> This leads me to the conclusion that the parent gdb is causing SIGCHLD
> to be blocked for the inferior (child) gdb.
> 
> Note that this problem could occur in other settings as well.  If gdb
> is invoked by a gui which communicates with it, the signal mask could
> be in an unknown/undesirable state too.
> 
> I think we should attack this problem on two fronts:
> 
>     1) Early in gdb's initialization, we should set the signal mask
>        to some appropriate value.  (Perhaps just unblock all signals.)
> 
>     2) Just after forking the child (on the child's side of the fork),
>        we should again reset the signal mask so that the child does
>        not inherit the mask that gdb is using.
> 
> I also think it's prudent to make sure that linuxthreads_block_mask
> does not block SIGCHLD.
> 
> Opinions?
> 
I think I have more or less understood what's going on:
1) After having read (once more ;-) the POSIX specification on exec() (3.1.2),
	I have [re]discovered that the process signal mask and pending signals
	are inherited by the new process image.
2) Michael's new 'linuxthreads_wait_mask' is computed by installing the new
	signal mask (blocking SIGCHLD) in '_initialize_linuxthreads()'.
3) Unfortunately, '_initialize_linuxthreads()' is part of the initialization
	routines which are systematically called by 'gdb_init()', whether or
	not LinuxThreads are used by the debugged process.

The result is that, when you run gdb on gdb, the top level gdb runs
	'_initialize_linuxthreads()' which blocks SIGCHLD. Then, it forks
	the debugged gdb, but does not reset the SIGNAL mask, so that the
	SIGCHLD is also blocked in the debugged GDB, thus leading to the
	behaviour you've noticed. Notice that when you run gdb on any
	program, the SIGCHLD of the program is also blocked (unless it
	resets its signal mask), leading to the behaviour you've noticed.

My recommendation would be to remove the signal mask modification from
	'_initialize_linuxthreads()', and to move it to places where
	'push_target (&linuxthreads_op)' is done (actually in
	'linuxthreads_attach()' and 'linuxthreads_create_inferior()'), and
	to restore original signal mask (linuxthreads_block_mask) in places
	where 'unpush_target (&linuxthreads_ops)' is done (actually in
	'linuxthreads_detach()' and 'linuxthreads_mourn_inferior()'),
	is that the signal mask handling is cleanly managed by linuxthread
	package.

This should fix your current problem. Concerning the reset of the signal mask
	in early GDB's initialization and just after forking the child, I
	don't think that this is necessary, since the SIGCHLD bug seems to
	be a misplacement of the signal mask handling in linuxthread support.
	My opinion is that if such problem arise once more, then this is
	because signal handling is not correctly handled by GDB targets.

Finally, the fact that signals are not blocked with gdb-4.17.0.11 is that
	my original patches on gdb-4.17 did not block SIGCHLD, but this
	lead to high load in GDB due to useless SIGCHLD handling on thread
	event (one SIGCHLD each time a thread was stopped or restarted).
	Michael and I discussed the idea of blocking SIGCHLD to reduce
	the GDB overhead on thread stopping/restarting.

Hope this helps,
-Eric
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ Eric PAIRE
Web  : http://www.ri.silicomp.com/~paire  | Group SILICOMP - Research Institute
Email: eric.paire@ri.silicomp.com         | 2, avenue de Vignate
Phone: +33 (0) 476 63 48 71               | F-38610 Gieres
Fax  : +33 (0) 476 51 05 32               | FRANCE


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