1 /* Low level interface for debugging GNU/Linux threads for GDB,
3 Copyright 1998, 1999 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* This module implements the debugging interface of the linuxthreads package
22 of the glibc. This package implements a simple clone()-based implementation
23 of Posix threads for Linux. To use this module, be sure that you have at
24 least the version of the linuxthreads package that holds the support of
25 GDB (currently 0.8 included in the glibc-2.0.7).
27 Right now, the linuxthreads package does not care of priority scheduling,
28 so, neither this module does; In particular, the threads are resumed
29 in any order, which could lead to different scheduling than the one
30 happening when GDB does not control the execution.
32 The latest point is that ptrace(PT_ATTACH, ...) is intrusive in Linux:
33 When a process is attached, then the attaching process becomes the current
34 parent of the attached process, and the old parent has lost this child.
35 If the old parent does a wait[...](), then this child is no longer
36 considered by the kernel as a child of the old parent, thus leading to
37 results of the call different when the child is attached and when it's not.
39 A fix has been submitted to the Linux community to solve this problem,
40 which consequences are not visible to the application itself, but on the
41 process which may wait() for the completion of the application (mostly,
42 it may consider that the application no longer exists (errno == ECHILD),
43 although it does, and thus being unable to get the exit status and resource
44 usage of the child. If by chance, it is able to wait() for the application
45 after it has died (by receiving first a SIGCHILD, and then doing a wait(),
46 then the exit status and resource usage may be wrong, because the
47 linuxthreads package heavily relies on wait() synchronization to keep
50 #include <sys/types.h> /* for pid_t */
51 #include <sys/ptrace.h> /* for PT_* flags */
52 #include <sys/wait.h> /* for WUNTRACED and __WCLONE flags */
53 #include <signal.h> /* for struct sigaction and NSIG */
54 #include <sys/utsname.h>
60 #include "gdbthread.h"
63 #include "breakpoint.h"
66 #define PT_ATTACH PTRACE_ATTACH
69 #define PT_KILL PTRACE_KILL
72 #define PT_READ_U PTRACE_PEEKUSR
76 #define LINUXTHREAD_NSIG NSIG
79 #define LINUXTHREAD_NSIG _NSIG
83 extern int child_suppress_run
; /* make inftarg.c non-runnable */
84 struct target_ops linuxthreads_ops
; /* Forward declaration */
85 extern struct target_ops child_ops
; /* target vector for inftarg.c */
87 static CORE_ADDR linuxthreads_handles
; /* array of linuxthreads handles */
88 static CORE_ADDR linuxthreads_manager
; /* pid of linuxthreads manager thread */
89 static CORE_ADDR linuxthreads_initial
; /* pid of linuxthreads initial thread */
90 static CORE_ADDR linuxthreads_debug
; /* linuxthreads internal debug flag */
91 static CORE_ADDR linuxthreads_num
; /* number of valid handle entries */
93 static int linuxthreads_max
; /* Maximum number of linuxthreads.
94 Zero if this executable doesn't use
95 threads, or wasn't linked with a
96 debugger-friendly version of the
97 linuxthreads library. */
99 static int linuxthreads_sizeof_handle
; /* size of a linuxthreads handle */
100 static int linuxthreads_offset_descr
; /* h_descr offset of the linuxthreads
102 static int linuxthreads_offset_pid
; /* p_pid offset of the linuxthreads
105 static int linuxthreads_manager_pid
; /* manager pid */
106 static int linuxthreads_initial_pid
; /* initial pid */
108 /* These variables form a bag of threads with interesting status. If
109 wait_thread (PID) finds that PID stopped for some interesting
110 reason (i.e. anything other than stopped with SIGSTOP), then it
111 records its status in this queue. linuxthreads_wait and
112 linuxthreads_find_trap extract processes from here. */
113 static int *linuxthreads_wait_pid
; /* wait array of pid */
114 static int *linuxthreads_wait_status
; /* wait array of status */
115 static int linuxthreads_wait_last
; /* index of last valid elt in
116 linuxthreads_wait_{pid,status} */
118 static sigset_t linuxthreads_wait_mask
; /* sigset with SIGCHLD */
120 static int linuxthreads_step_pid
; /* current stepped pid */
121 static int linuxthreads_step_signo
; /* current stepped target signal */
122 static int linuxthreads_exit_status
; /* exit status of initial thread */
124 static int linuxthreads_inferior_pid
; /* temporary internal inferior pid */
125 static int linuxthreads_breakpoint_pid
; /* last pid that hit a breakpoint */
126 static int linuxthreads_attach_pending
; /* attach command without wait */
128 static int linuxthreads_breakpoints_inserted
; /* any breakpoints inserted */
130 /* LinuxThreads uses certain signals for communication between
131 processes; we need to tell GDB to pass them through silently to the
132 inferior. The LinuxThreads library has global variables we can
133 read containing the relevant signal numbers, but since the signal
134 numbers are chosen at run-time, those variables aren't initialized
135 until the shared library's constructors have had a chance to run. */
137 struct linuxthreads_signal
{
139 /* The name of the LinuxThreads library variable that contains
140 the signal number. */
143 /* True if this variable must exist for us to debug properly. */
146 /* The variable's address in the inferior, or zero if the
147 LinuxThreads library hasn't been loaded into this inferior yet. */
150 /* The signal number, or zero if we don't know yet (either because
151 we haven't found the variable, or it hasn't been initialized).
152 This is an actual target signal number that you could pass to
153 `kill', not a GDB signal number. */
156 /* GDB's original settings for `stop' and `print' for this signal.
157 We restore them when the user selects a different executable.
158 Invariant: if sig->signal != 0, then sig->{stop,print} contain
159 the original settings. */
163 struct linuxthreads_signal linuxthreads_sig_restart
= {
164 "__pthread_sig_restart", 1, 0, 0, 0, 0
166 struct linuxthreads_signal linuxthreads_sig_cancel
= {
167 "__pthread_sig_cancel", 1, 0, 0, 0, 0
169 struct linuxthreads_signal linuxthreads_sig_debug
= {
170 "__pthread_sig_debug", 0, 0, 0, 0, 0
173 /* A table of breakpoint locations, one per PID. */
174 static struct linuxthreads_breakpoint
{
175 CORE_ADDR pc
; /* PC of breakpoint */
176 int pid
; /* pid of breakpoint */
177 int step
; /* whether the pc has been reached after sstep */
178 } *linuxthreads_breakpoint_zombie
; /* Zombie breakpoints array */
179 static int linuxthreads_breakpoint_last
; /* Last zombie breakpoint */
181 /* linuxthreads_{insert,remove}_breakpoint pass the breakpoint address
182 to {insert,remove}_breakpoint via this variable, since
183 iterate_active_threads doesn't provide any way to pass values
184 through to the worker function. */
185 static CORE_ADDR linuxthreads_breakpoint_addr
;
187 #define REMOVE_BREAKPOINT_ZOMBIE(_i) \
189 if ((_i) < linuxthreads_breakpoint_last) \
190 linuxthreads_breakpoint_zombie[(_i)] = \
191 linuxthreads_breakpoint_zombie[linuxthreads_breakpoint_last]; \
192 linuxthreads_breakpoint_last--; \
197 #ifndef PTRACE_XFER_TYPE
198 #define PTRACE_XFER_TYPE int
200 /* Check to see if the given thread is alive. */
202 linuxthreads_thread_alive (pid
)
206 return ptrace (PT_READ_U
, pid
, (PTRACE_ARG3_TYPE
)0, 0) >= 0 || errno
== 0;
209 /* On detach(), find a SIGTRAP status. If stop is non-zero, find a
212 Make sure PID is ready to run, and free of interference from our
213 efforts to debug it (e.g., pending SIGSTOP or SIGTRAP signals). If
214 STOP is zero, just look for a SIGTRAP. If STOP is non-zero, look
215 for a SIGSTOP, too. Return non-zero if PID is alive and ready to
216 run; return zero if PID is dead.
218 PID may or may not be stopped at the moment, and we may or may not
219 have waited for it already. We check the linuxthreads_wait bag in
220 case we've already got a status for it. We may possibly wait for
223 PID may have signals waiting to be delivered. If they're caused by
224 our efforts to debug it, accept them with wait, but don't pass them
225 through to PID. Do pass all other signals through. */
227 linuxthreads_find_trap (pid
, stop
)
237 /* PID may have any number of signals pending. The kernel will
238 report each of them to us via wait, and then it's up to us to
239 pass them along to the process via ptrace, if we so choose.
241 We need to paw through the whole set until we've found a SIGTRAP
242 (or a SIGSTOP, if `stop' is set). We don't pass the SIGTRAP (or
243 SIGSTOP) through, but we do re-send all the others, so PID will
244 receive them when we resume it. */
245 int *wstatus
= alloca (LINUXTHREAD_NSIG
* sizeof (int));
248 /* Look at the pending status */
249 for (i
= linuxthreads_wait_last
; i
>= 0; i
--)
250 if (linuxthreads_wait_pid
[i
] == pid
)
252 status
= linuxthreads_wait_status
[i
];
254 /* Delete the i'th member of the table. Since the table is
255 unordered, we can do this simply by copying the table's
256 last element to the i'th position, and shrinking the table
258 if (i
< linuxthreads_wait_last
)
260 linuxthreads_wait_status
[i
] =
261 linuxthreads_wait_status
[linuxthreads_wait_last
];
262 linuxthreads_wait_pid
[i
] =
263 linuxthreads_wait_pid
[linuxthreads_wait_last
];
265 linuxthreads_wait_last
--;
267 if (!WIFSTOPPED(status
)) /* Thread has died */
270 if (WSTOPSIG(status
) == SIGTRAP
)
277 else if (WSTOPSIG(status
) == SIGSTOP
)
293 /* Make sure that we'll find what we're looking for. */
300 /* Catch all status until SIGTRAP and optionally SIGSTOP show up. */
303 child_resume (pid
, 1, TARGET_SIGNAL_0
);
307 rpid
= waitpid (pid
, &status
, __WCLONE
);
313 /* There are a few reasons the wait call above may have
314 failed. If the thread manager dies, its children get
315 reparented, and this interferes with GDB waiting for
316 them, in some cases. Another possibility is that the
317 initial thread was not cloned, so calling wait with
318 __WCLONE won't find it. I think neither of these should
319 occur in modern Linux kernels --- they don't seem to in
321 rpid
= waitpid (pid
, &status
, 0);
325 perror_with_name ("waitpid");
328 if (!WIFSTOPPED(status
)) /* Thread has died */
331 if (WSTOPSIG(status
) == SIGTRAP
)
332 if (!stop
|| found_stop
)
336 else if (WSTOPSIG(status
) != SIGSTOP
)
337 wstatus
[last
++] = status
;
347 /* Resend any other signals we noticed to the thread, to be received
348 when we continue it. */
350 kill (pid
, WSTOPSIG(wstatus
[last
]));
355 /* Cleanup stub for save_inferior_pid. */
357 restore_inferior_pid (arg
)
364 /* Register a cleanup to restore the value of inferior_pid. */
365 static struct cleanup
*
368 return make_cleanup (restore_inferior_pid
, (void *) inferior_pid
);
372 sigchld_handler (signo
)
375 /* This handler is used to get an EINTR while doing waitpid()
376 when an event is received */
379 /* Have we already collected a wait status for PID in the
380 linuxthreads_wait bag? */
382 linuxthreads_pending_status (pid
)
386 for (i
= linuxthreads_wait_last
; i
>= 0; i
--)
387 if (linuxthreads_wait_pid
[i
] == pid
)
393 /* Internal linuxthreads signal management */
395 /* Check in OBJFILE for the variable that holds the number for signal SIG.
396 We assume that we've already found other LinuxThreads-ish variables
397 in OBJFILE, so we complain if it's required, but not there.
398 Return true iff things are okay. */
400 find_signal_var (sig
, objfile
)
401 struct linuxthreads_signal
*sig
;
402 struct objfile
*objfile
;
404 struct minimal_symbol
*ms
= lookup_minimal_symbol (sig
->var
, NULL
, objfile
);
410 fprintf_unfiltered (gdb_stderr
,
411 "Unable to find linuxthreads symbol \"%s\"\n",
422 sig
->addr
= SYMBOL_VALUE_ADDRESS (ms
);
428 find_all_signal_vars (objfile
)
429 struct objfile
*objfile
;
431 return ( find_signal_var (&linuxthreads_sig_restart
, objfile
)
432 && find_signal_var (&linuxthreads_sig_cancel
, objfile
)
433 && find_signal_var (&linuxthreads_sig_debug
, objfile
));
436 /* A struct complaint isn't appropriate here. */
437 static int complained_cannot_determine_thread_signal_number
= 0;
439 /* Check to see if the variable holding the signal number for SIG has
440 been initialized yet. If it has, tell GDB to pass that signal
441 through to the inferior silently. */
443 check_signal_number (sig
)
444 struct linuxthreads_signal
*sig
;
449 /* We already know this signal number. */
453 /* We don't know the variable's address yet. */
456 if (target_read_memory (sig
->addr
, (char *)&num
, sizeof (num
))
459 /* If this happens once, it'll probably happen for all the
460 signals, so only complain once. */
461 if (! complained_cannot_determine_thread_signal_number
)
462 warning ("Cannot determine thread signal number; "
463 "GDB may report spurious signals.");
464 complained_cannot_determine_thread_signal_number
= 1;
469 /* It hasn't been initialized yet. */
472 /* We know sig->signal was zero, and is becoming non-zero, so it's
473 okay to sample GDB's original settings. */
475 sig
->stop
= signal_stop_update (target_signal_from_host (num
), 0);
476 sig
->print
= signal_print_update (target_signal_from_host (num
), 0);
481 check_all_signal_numbers ()
483 /* If this isn't a LinuxThreads program, quit early. */
484 if (! linuxthreads_max
)
487 check_signal_number (&linuxthreads_sig_restart
);
488 check_signal_number (&linuxthreads_sig_cancel
);
489 check_signal_number (&linuxthreads_sig_debug
);
491 /* handle linuxthread exit */
492 if (linuxthreads_sig_debug
.signal
493 || linuxthreads_sig_restart
.signal
)
495 struct sigaction sact
;
497 sact
.sa_handler
= sigchld_handler
;
498 sigemptyset(&sact
.sa_mask
);
500 if (linuxthreads_sig_debug
.signal
> 0)
501 sigaction(linuxthreads_sig_cancel
.signal
, &sact
, NULL
);
503 sigaction(linuxthreads_sig_restart
.signal
, &sact
, NULL
);
508 /* Restore GDB's original settings for SIG.
509 This should only be called when we're no longer sure if we're
510 talking to an executable that uses LinuxThreads, so we clear the
511 signal number and variable address too. */
514 struct linuxthreads_signal
*sig
;
519 /* We know sig->signal was non-zero, and is becoming zero, so it's
520 okay to restore GDB's original settings. */
521 signal_stop_update (target_signal_from_host (sig
->signal
), sig
->stop
);
522 signal_print_update (target_signal_from_host (sig
->signal
), sig
->print
);
529 /* Restore GDB's original settings for all LinuxThreads signals.
530 This should only be called when we're no longer sure if we're
531 talking to an executable that uses LinuxThreads, so we clear the
532 signal number and variable address too. */
534 restore_all_signals ()
536 restore_signal (&linuxthreads_sig_restart
);
537 restore_signal (&linuxthreads_sig_cancel
);
538 restore_signal (&linuxthreads_sig_debug
);
540 /* If it happens again, we should complain again. */
541 complained_cannot_determine_thread_signal_number
= 0;
547 /* Apply FUNC to the pid of each active thread. This consults the
548 inferior's handle table to find active threads.
550 If ALL is non-zero, process all threads.
551 If ALL is zero, skip threads with pending status. */
553 iterate_active_threads (func
, all
)
562 read_memory (linuxthreads_num
, (char *)&num
, sizeof (int));
564 for (i
= 0; i
< linuxthreads_max
&& num
> 0; i
++)
566 read_memory (linuxthreads_handles
+
567 linuxthreads_sizeof_handle
* i
+ linuxthreads_offset_descr
,
568 (char *)&descr
, sizeof (void *));
572 read_memory (descr
+ linuxthreads_offset_pid
,
573 (char *)&pid
, sizeof (pid_t
));
574 if (pid
> 0 && pid
!= linuxthreads_manager_pid
575 && (all
|| (!linuxthreads_pending_status (pid
))))
582 /* Insert a thread breakpoint at linuxthreads_breakpoint_addr.
583 This is the worker function for linuxthreads_insert_breakpoint,
584 which passes it to iterate_active_threads. */
586 insert_breakpoint (pid
)
591 /* Remove (if any) the positive zombie breakpoint. */
592 for (j
= linuxthreads_breakpoint_last
; j
>= 0; j
--)
593 if (linuxthreads_breakpoint_zombie
[j
].pid
== pid
)
595 if ((linuxthreads_breakpoint_zombie
[j
].pc
- DECR_PC_AFTER_BREAK
596 == linuxthreads_breakpoint_addr
)
597 && !linuxthreads_breakpoint_zombie
[j
].step
)
598 REMOVE_BREAKPOINT_ZOMBIE(j
);
603 /* Note that we're about to remove a thread breakpoint at
604 linuxthreads_breakpoint_addr.
606 This is the worker function for linuxthreads_remove_breakpoint,
607 which passes it to iterate_active_threads. The actual work of
608 overwriting the breakpoint instruction is done by
609 child_ops.to_remove_breakpoint; here, we simply create a zombie
610 breakpoint if the thread's PC is pointing at the breakpoint being
613 remove_breakpoint (pid
)
618 /* Insert a positive zombie breakpoint (if needed). */
619 for (j
= 0; j
<= linuxthreads_breakpoint_last
; j
++)
620 if (linuxthreads_breakpoint_zombie
[j
].pid
== pid
)
623 if (in_thread_list (pid
) && linuxthreads_thread_alive (pid
))
625 CORE_ADDR pc
= read_pc_pid (pid
);
626 if (linuxthreads_breakpoint_addr
== pc
- DECR_PC_AFTER_BREAK
627 && j
> linuxthreads_breakpoint_last
)
629 linuxthreads_breakpoint_zombie
[j
].pid
= pid
;
630 linuxthreads_breakpoint_zombie
[j
].pc
= pc
;
631 linuxthreads_breakpoint_zombie
[j
].step
= 0;
632 linuxthreads_breakpoint_last
++;
642 if (in_thread_list (pid
))
643 ptrace (PT_KILL
, pid
, (PTRACE_ARG3_TYPE
) 0, 0);
648 /* Resume a thread */
653 if (pid
!= inferior_pid
654 && in_thread_list (pid
)
655 && linuxthreads_thread_alive (pid
))
657 if (pid
== linuxthreads_step_pid
)
658 child_resume (pid
, 1, linuxthreads_step_signo
);
660 child_resume (pid
, 0, TARGET_SIGNAL_0
);
664 /* Detach a thread */
669 if (in_thread_list (pid
) && linuxthreads_thread_alive (pid
))
671 /* Remove pending SIGTRAP and SIGSTOP */
672 linuxthreads_find_trap (pid
, 1);
675 detach (TARGET_SIGNAL_0
);
676 inferior_pid
= linuxthreads_manager_pid
;
685 if (pid
!= inferior_pid
)
687 if (in_thread_list (pid
))
689 else if (ptrace (PT_ATTACH
, pid
, (PTRACE_ARG3_TYPE
) 0, 0) == 0)
691 if (!linuxthreads_attach_pending
)
692 printf_unfiltered ("[New %s]\n", target_pid_to_str (pid
));
694 if (linuxthreads_sig_debug
.signal
)
695 /* After a new thread in glibc 2.1 signals gdb its existence,
696 it suspends itself and wait for linuxthreads_sig_restart,
697 now we can wake up it. */
698 kill (pid
, linuxthreads_sig_restart
.signal
);
701 perror_with_name ("ptrace in stop_thread");
705 /* Wait for a thread */
713 if (pid
!= inferior_pid
&& in_thread_list (pid
))
717 /* Get first pid status. */
718 rpid
= waitpid(pid
, &status
, __WCLONE
);
724 /* There are two reasons this might have failed:
726 1) PID is the initial thread, which wasn't cloned, so
727 passing the __WCLONE flag to waitpid prevented us from
730 2) The manager thread is the parent of all but the
731 initial thread; if it dies, the children will all be
732 reparented to init, which will wait for them. This means
733 our call to waitpid won't find them.
735 Actually, based on a casual look at the 2.0.36 kernel
736 code, I don't think either of these cases happen. But I
737 don't have things set up for remotely debugging the
738 kernel, so I'm not sure. And perhaps older kernels
740 rpid
= waitpid(pid
, &status
, 0);
743 if (errno
!= EINTR
&& linuxthreads_thread_alive (pid
))
744 perror_with_name ("waitpid");
746 /* the thread is dead. */
749 if (!WIFSTOPPED(status
) || WSTOPSIG(status
) != SIGSTOP
)
751 linuxthreads_wait_pid
[++linuxthreads_wait_last
] = pid
;
752 linuxthreads_wait_status
[linuxthreads_wait_last
] = status
;
757 /* Walk through the linuxthreads handles in order to detect all
758 threads and stop them */
760 update_stop_threads (test_pid
)
763 struct cleanup
*old_chain
= NULL
;
765 check_all_signal_numbers ();
767 if (linuxthreads_manager_pid
== 0)
769 if (linuxthreads_manager
)
771 if (test_pid
> 0 && test_pid
!= inferior_pid
)
773 old_chain
= save_inferior_pid ();
774 inferior_pid
= test_pid
;
776 read_memory (linuxthreads_manager
,
777 (char *)&linuxthreads_manager_pid
, sizeof (pid_t
));
779 if (linuxthreads_initial
)
781 if (test_pid
> 0 && test_pid
!= inferior_pid
)
783 old_chain
= save_inferior_pid ();
784 inferior_pid
= test_pid
;
786 read_memory(linuxthreads_initial
,
787 (char *)&linuxthreads_initial_pid
, sizeof (pid_t
));
791 if (linuxthreads_manager_pid
!= 0)
793 if (old_chain
== NULL
&& test_pid
> 0 &&
794 test_pid
!= inferior_pid
&& linuxthreads_thread_alive (test_pid
))
796 old_chain
= save_inferior_pid ();
797 inferior_pid
= test_pid
;
800 if (linuxthreads_thread_alive (inferior_pid
))
804 if (test_pid
!= linuxthreads_manager_pid
805 && !linuxthreads_pending_status (linuxthreads_manager_pid
))
807 stop_thread (linuxthreads_manager_pid
);
808 wait_thread (linuxthreads_manager_pid
);
810 if (!in_thread_list (test_pid
))
812 if (!linuxthreads_attach_pending
)
813 printf_unfiltered ("[New %s]\n",
814 target_pid_to_str (test_pid
));
815 add_thread (test_pid
);
816 if (linuxthreads_sig_debug
.signal
817 && inferior_pid
== test_pid
)
818 /* After a new thread in glibc 2.1 signals gdb its
819 existence, it suspends itself and wait for
820 linuxthreads_sig_restart, now we can wake up
822 kill (test_pid
, linuxthreads_sig_restart
.signal
);
825 iterate_active_threads (stop_thread
, 0);
826 iterate_active_threads (wait_thread
, 0);
830 if (old_chain
!= NULL
)
831 do_cleanups (old_chain
);
834 /* This routine is called whenever a new symbol table is read in, or when all
835 symbol tables are removed. libpthread can only be initialized when it
836 finds the right variables in libpthread.so. Since it's a shared library,
837 those variables don't show up until the library gets mapped and the symbol
841 linuxthreads_new_objfile (objfile
)
842 struct objfile
*objfile
;
844 struct minimal_symbol
*ms
;
848 /* We're starting an entirely new executable, so we can no
849 longer be sure that it uses LinuxThreads. Restore the signal
850 flags to their original states. */
851 restore_all_signals ();
853 /* Indicate that we don't know anything's address any more. */
854 linuxthreads_max
= 0;
859 /* If we've already found our variables in another objfile, don't
860 bother looking for them again. */
861 if (linuxthreads_max
)
864 if (! lookup_minimal_symbol ("__pthread_initial_thread", NULL
, objfile
))
865 /* This object file isn't the pthreads library. */
868 if ((ms
= lookup_minimal_symbol ("__pthread_threads_debug",
869 NULL
, objfile
)) == NULL
)
871 /* The debugging-aware libpthreads is not present in this objfile */
873 This program seems to use POSIX threads, but the thread library used\n\
874 does not support debugging. This may make using GDB difficult. Don't\n\
875 set breakpoints or single-step through code that might be executed by\n\
876 any thread other than the main thread.");
879 linuxthreads_debug
= SYMBOL_VALUE_ADDRESS (ms
);
881 /* Read internal structures configuration */
882 if ((ms
= lookup_minimal_symbol ("__pthread_sizeof_handle",
883 NULL
, objfile
)) == NULL
884 || target_read_memory (SYMBOL_VALUE_ADDRESS (ms
),
885 (char *)&linuxthreads_sizeof_handle
,
886 sizeof (linuxthreads_sizeof_handle
)) != 0)
888 fprintf_unfiltered (gdb_stderr
,
889 "Unable to find linuxthreads symbol \"%s\"\n",
890 "__pthread_sizeof_handle");
894 if ((ms
= lookup_minimal_symbol ("__pthread_offsetof_descr",
895 NULL
, objfile
)) == NULL
896 || target_read_memory (SYMBOL_VALUE_ADDRESS (ms
),
897 (char *)&linuxthreads_offset_descr
,
898 sizeof (linuxthreads_offset_descr
)) != 0)
900 fprintf_unfiltered (gdb_stderr
,
901 "Unable to find linuxthreads symbol \"%s\"\n",
902 "__pthread_offsetof_descr");
906 if ((ms
= lookup_minimal_symbol ("__pthread_offsetof_pid",
907 NULL
, objfile
)) == NULL
908 || target_read_memory (SYMBOL_VALUE_ADDRESS (ms
),
909 (char *)&linuxthreads_offset_pid
,
910 sizeof (linuxthreads_offset_pid
)) != 0)
912 fprintf_unfiltered (gdb_stderr
,
913 "Unable to find linuxthreads symbol \"%s\"\n",
914 "__pthread_offsetof_pid");
918 if (! find_all_signal_vars (objfile
))
921 /* Read adresses of internal structures to access */
922 if ((ms
= lookup_minimal_symbol ("__pthread_handles",
923 NULL
, objfile
)) == NULL
)
925 fprintf_unfiltered (gdb_stderr
,
926 "Unable to find linuxthreads symbol \"%s\"\n",
927 "__pthread_handles");
930 linuxthreads_handles
= SYMBOL_VALUE_ADDRESS (ms
);
932 if ((ms
= lookup_minimal_symbol ("__pthread_handles_num",
933 NULL
, objfile
)) == NULL
)
935 fprintf_unfiltered (gdb_stderr
,
936 "Unable to find linuxthreads symbol \"%s\"\n",
937 "__pthread_handles_num");
940 linuxthreads_num
= SYMBOL_VALUE_ADDRESS (ms
);
942 if ((ms
= lookup_minimal_symbol ("__pthread_manager_thread",
943 NULL
, objfile
)) == NULL
)
945 fprintf_unfiltered (gdb_stderr
,
946 "Unable to find linuxthreads symbol \"%s\"\n",
947 "__pthread_manager_thread");
950 linuxthreads_manager
= SYMBOL_VALUE_ADDRESS (ms
) + linuxthreads_offset_pid
;
952 if ((ms
= lookup_minimal_symbol ("__pthread_initial_thread",
953 NULL
, objfile
)) == NULL
)
955 fprintf_unfiltered (gdb_stderr
,
956 "Unable to find linuxthreads symbol \"%s\"\n",
957 "__pthread_initial_thread");
960 linuxthreads_initial
= SYMBOL_VALUE_ADDRESS (ms
) + linuxthreads_offset_pid
;
962 /* Search for this last, so it won't be set to a non-zero value unless
963 we successfully found all the symbols above. */
964 if ((ms
= lookup_minimal_symbol ("__pthread_threads_max",
965 NULL
, objfile
)) == NULL
966 || target_read_memory (SYMBOL_VALUE_ADDRESS (ms
),
967 (char *)&linuxthreads_max
,
968 sizeof (linuxthreads_max
)) != 0)
970 fprintf_unfiltered (gdb_stderr
,
971 "Unable to find linuxthreads symbol \"%s\"\n",
972 "__pthread_threads_max");
976 /* Allocate gdb internal structures */
977 linuxthreads_wait_pid
=
978 (int *) xmalloc (sizeof (int) * (linuxthreads_max
+ 1));
979 linuxthreads_wait_status
=
980 (int *) xmalloc (sizeof (int) * (linuxthreads_max
+ 1));
981 linuxthreads_breakpoint_zombie
= (struct linuxthreads_breakpoint
*)
982 xmalloc (sizeof (struct linuxthreads_breakpoint
) * (linuxthreads_max
+ 1));
984 if (inferior_pid
&& !linuxthreads_attach_pending
)
987 target_write_memory (linuxthreads_debug
, (char *)&on
, sizeof (on
));
988 linuxthreads_attach_pending
= 1;
989 update_stop_threads (inferior_pid
);
990 linuxthreads_attach_pending
= 0;
994 /* If we have switched threads from a one that stopped at breakpoint,
995 return 1 otherwise 0. */
998 linuxthreads_prepare_to_proceed (step
)
1001 if (!linuxthreads_max
1002 || !linuxthreads_manager_pid
1003 || !linuxthreads_breakpoint_pid
1004 || !breakpoint_here_p (read_pc_pid (linuxthreads_breakpoint_pid
)))
1009 /* Mark the current inferior as single stepping process. */
1010 linuxthreads_step_pid
= inferior_pid
;
1013 linuxthreads_inferior_pid
= linuxthreads_breakpoint_pid
;
1014 return linuxthreads_breakpoint_pid
;
1017 /* Convert a pid to printable form. */
1020 linuxthreads_pid_to_str (pid
)
1023 static char buf
[100];
1025 sprintf (buf
, "%s %d%s", linuxthreads_max
? "Thread" : "Pid", pid
,
1026 (pid
== linuxthreads_manager_pid
) ? " (manager thread)"
1027 : (pid
== linuxthreads_initial_pid
) ? " (initial thread)"
1033 /* Attach to process PID, then initialize for debugging it
1034 and wait for the trace-trap that results from attaching. */
1037 linuxthreads_attach (args
, from_tty
)
1042 error_no_arg ("process-id to attach");
1044 push_target (&linuxthreads_ops
);
1045 linuxthreads_breakpoints_inserted
= 1;
1046 linuxthreads_breakpoint_last
= -1;
1047 linuxthreads_wait_last
= -1;
1048 linuxthreads_exit_status
= __W_STOPCODE(0);
1050 child_ops
.to_attach (args
, from_tty
);
1052 if (linuxthreads_max
)
1053 linuxthreads_attach_pending
= 1;
1056 /* Take a program previously attached to and detaches it.
1057 The program resumes execution and will no longer stop
1058 on signals, etc. We'd better not have left any breakpoints
1059 in the program or it'll die when it hits one. For this
1060 to work, it may be necessary for the process to have been
1061 previously attached. It *might* work if the program was
1062 started via the normal ptrace (PTRACE_TRACEME). */
1065 linuxthreads_detach (args
, from_tty
)
1069 if (linuxthreads_max
)
1074 target_write_memory (linuxthreads_debug
, (char *)&off
, sizeof (off
));
1076 /* Walk through linuxthreads array in order to detach known threads. */
1077 if (linuxthreads_manager_pid
!= 0)
1079 /* Get rid of all positive zombie breakpoints. */
1080 for (i
= 0; i
<= linuxthreads_breakpoint_last
; i
++)
1082 if (linuxthreads_breakpoint_zombie
[i
].step
)
1085 pid
= linuxthreads_breakpoint_zombie
[i
].pid
;
1086 if (!linuxthreads_thread_alive (pid
))
1089 if (linuxthreads_breakpoint_zombie
[i
].pc
!= read_pc_pid (pid
))
1092 /* Continue in STEP mode until the thread pc has moved or
1093 until SIGTRAP is found on the same PC. */
1094 if (linuxthreads_find_trap (pid
, 0)
1095 && linuxthreads_breakpoint_zombie
[i
].pc
== read_pc_pid (pid
))
1096 write_pc_pid (linuxthreads_breakpoint_zombie
[i
].pc
1097 - DECR_PC_AFTER_BREAK
, pid
);
1100 /* Detach thread after thread. */
1101 inferior_pid
= linuxthreads_manager_pid
;
1102 iterate_active_threads (detach_thread
, 1);
1104 /* Remove pending SIGTRAP and SIGSTOP */
1105 linuxthreads_find_trap (inferior_pid
, 1);
1107 linuxthreads_wait_last
= -1;
1108 linuxthreads_exit_status
= __W_STOPCODE(0);
1111 linuxthreads_inferior_pid
= 0;
1112 linuxthreads_breakpoint_pid
= 0;
1113 linuxthreads_step_pid
= 0;
1114 linuxthreads_step_signo
= TARGET_SIGNAL_0
;
1115 linuxthreads_manager_pid
= 0;
1116 linuxthreads_initial_pid
= 0;
1117 linuxthreads_attach_pending
= 0;
1118 init_thread_list (); /* Destroy thread info */
1121 child_ops
.to_detach (args
, from_tty
);
1123 unpush_target (&linuxthreads_ops
);
1126 /* Resume execution of process PID. If STEP is nozero, then
1127 just single step it. If SIGNAL is nonzero, restart it with that
1128 signal activated. */
1131 linuxthreads_resume (pid
, step
, signo
)
1134 enum target_signal signo
;
1136 if (!linuxthreads_max
|| stop_soon_quietly
|| linuxthreads_manager_pid
== 0)
1137 child_ops
.to_resume (pid
, step
, signo
);
1141 if (linuxthreads_inferior_pid
)
1143 /* Prepare resume of the last thread that hit a breakpoint */
1144 linuxthreads_breakpoints_inserted
= 0;
1145 rpid
= linuxthreads_inferior_pid
;
1146 linuxthreads_step_signo
= signo
;
1150 struct cleanup
*old_chain
= NULL
;
1155 linuxthreads_step_pid
= step
? inferior_pid
: 0;
1156 linuxthreads_step_signo
= signo
;
1157 rpid
= inferior_pid
;
1162 if (pid
< 0 || !step
)
1164 linuxthreads_breakpoints_inserted
= 1;
1166 /* Walk through linuxthreads array in order to resume threads */
1167 if (pid
>= 0 && inferior_pid
!= pid
)
1169 old_chain
= save_inferior_pid ();
1173 iterate_active_threads (resume_thread
, 0);
1174 if (linuxthreads_manager_pid
!= inferior_pid
1175 && !linuxthreads_pending_status (linuxthreads_manager_pid
))
1176 resume_thread (linuxthreads_manager_pid
);
1179 linuxthreads_breakpoints_inserted
= 0;
1181 /* Deal with zombie breakpoint */
1182 for (i
= 0; i
<= linuxthreads_breakpoint_last
; i
++)
1183 if (linuxthreads_breakpoint_zombie
[i
].pid
== rpid
)
1185 if (linuxthreads_breakpoint_zombie
[i
].pc
!= read_pc_pid (rpid
))
1187 /* The current pc is out of zombie breakpoint. */
1188 REMOVE_BREAKPOINT_ZOMBIE(i
);
1193 if (old_chain
!= NULL
)
1194 do_cleanups (old_chain
);
1197 /* Resume initial thread. */
1198 if (!linuxthreads_pending_status (rpid
))
1199 child_ops
.to_resume (rpid
, step
, signo
);
1203 /* Wait for any threads to stop. We may have to convert PID from a thread id
1204 to a LWP id, and vice versa on the way out. */
1207 linuxthreads_wait (pid
, ourstatus
)
1209 struct target_waitstatus
*ourstatus
;
1217 if (linuxthreads_max
&& !linuxthreads_breakpoints_inserted
)
1218 wstatus
= alloca (LINUXTHREAD_NSIG
* sizeof (int));
1220 /* See if the inferior has chosen values for its signals yet. By
1221 checking for them here, we can be sure we've updated GDB's signal
1222 handling table before the inferior ever gets one of them. (Well,
1223 before we notice, anyway.) */
1224 check_all_signal_numbers ();
1228 if (!linuxthreads_max
)
1230 else if (!linuxthreads_breakpoints_inserted
)
1232 if (linuxthreads_inferior_pid
)
1233 pid
= linuxthreads_inferior_pid
;
1238 else if (pid
< 0 && linuxthreads_wait_last
>= 0)
1240 status
= linuxthreads_wait_status
[linuxthreads_wait_last
];
1241 rpid
= linuxthreads_wait_pid
[linuxthreads_wait_last
--];
1243 else if (pid
> 0 && linuxthreads_pending_status (pid
))
1245 for (i
= linuxthreads_wait_last
; i
>= 0; i
--)
1246 if (linuxthreads_wait_pid
[i
] == pid
)
1252 status
= linuxthreads_wait_status
[i
];
1254 if (i
< linuxthreads_wait_last
)
1256 linuxthreads_wait_status
[i
] =
1257 linuxthreads_wait_status
[linuxthreads_wait_last
];
1258 linuxthreads_wait_pid
[i
] =
1259 linuxthreads_wait_pid
[linuxthreads_wait_last
];
1261 linuxthreads_wait_last
--;
1272 set_sigint_trap(); /* Causes SIGINT to be passed on to the
1273 attached process. */
1276 sigprocmask(SIG_BLOCK
, &linuxthreads_wait_mask
, &omask
);
1279 rpid
= waitpid (pid
, &status
, __WCLONE
| WNOHANG
);
1284 else if (errno
!= EINTR
)
1289 rpid
= waitpid (pid
, &status
, WNOHANG
);
1296 else if (save_errno
!= 0)
1302 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1305 clear_sigio_trap ();
1307 clear_sigint_trap();
1311 if (WIFEXITED(linuxthreads_exit_status
))
1313 store_waitstatus (ourstatus
, linuxthreads_exit_status
);
1314 return inferior_pid
;
1319 (gdb_stderr
, "Child process unexpectedly missing: %s.\n",
1320 safe_strerror (save_errno
));
1321 /* Claim it exited with unknown signal. */
1322 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
1323 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
1328 /* Signals arrive in any order. So get all signals until SIGTRAP
1329 and resend previous ones to be held after. */
1330 if (linuxthreads_max
1331 && !linuxthreads_breakpoints_inserted
1332 && WIFSTOPPED(status
))
1333 if (WSTOPSIG(status
) == SIGTRAP
)
1336 kill (rpid
, WSTOPSIG(wstatus
[last
]));
1338 /* insert negative zombie breakpoint */
1339 for (i
= 0; i
<= linuxthreads_breakpoint_last
; i
++)
1340 if (linuxthreads_breakpoint_zombie
[i
].pid
== rpid
)
1342 if (i
> linuxthreads_breakpoint_last
)
1344 linuxthreads_breakpoint_zombie
[i
].pid
= rpid
;
1345 linuxthreads_breakpoint_last
++;
1347 linuxthreads_breakpoint_zombie
[i
].pc
= read_pc_pid (rpid
);
1348 linuxthreads_breakpoint_zombie
[i
].step
= 1;
1352 if (WSTOPSIG(status
) != SIGSTOP
)
1354 for (i
= 0; i
< last
; i
++)
1355 if (wstatus
[i
] == status
)
1358 wstatus
[last
++] = status
;
1360 child_resume (rpid
, 1, TARGET_SIGNAL_0
);
1363 if (linuxthreads_inferior_pid
)
1364 linuxthreads_inferior_pid
= 0;
1367 if (linuxthreads_max
&& !stop_soon_quietly
)
1369 if (linuxthreads_max
1370 && WIFSTOPPED(status
)
1371 && WSTOPSIG(status
) == SIGSTOP
)
1373 /* Skip SIGSTOP signals. */
1374 if (!linuxthreads_pending_status (rpid
))
1376 if (linuxthreads_step_pid
== rpid
)
1377 child_resume (rpid
, 1, linuxthreads_step_signo
);
1379 child_resume (rpid
, 0, TARGET_SIGNAL_0
);
1384 /* Do no report exit status of cloned threads. */
1385 if (WIFEXITED(status
))
1387 if (rpid
== linuxthreads_initial_pid
)
1388 linuxthreads_exit_status
= status
;
1390 /* Remove any zombie breakpoint. */
1391 for (i
= 0; i
<= linuxthreads_breakpoint_last
; i
++)
1392 if (linuxthreads_breakpoint_zombie
[i
].pid
== rpid
)
1394 REMOVE_BREAKPOINT_ZOMBIE(i
);
1402 /* Deal with zombie breakpoint */
1403 for (i
= 0; i
<= linuxthreads_breakpoint_last
; i
++)
1404 if (linuxthreads_breakpoint_zombie
[i
].pid
== rpid
)
1407 if (i
<= linuxthreads_breakpoint_last
)
1409 /* There is a potential zombie breakpoint */
1410 if (WIFEXITED(status
)
1411 || linuxthreads_breakpoint_zombie
[i
].pc
!= read_pc_pid (rpid
))
1413 /* The current pc is out of zombie breakpoint. */
1414 REMOVE_BREAKPOINT_ZOMBIE(i
);
1416 else if (!linuxthreads_breakpoint_zombie
[i
].step
1417 && WIFSTOPPED(status
) && WSTOPSIG(status
) == SIGTRAP
)
1419 /* This is a real one ==> decrement PC and restart. */
1420 write_pc_pid (linuxthreads_breakpoint_zombie
[i
].pc
1421 - DECR_PC_AFTER_BREAK
, rpid
);
1422 if (linuxthreads_step_pid
== rpid
)
1423 child_resume (rpid
, 1, linuxthreads_step_signo
);
1425 child_resume (rpid
, 0, TARGET_SIGNAL_0
);
1430 /* Walk through linuxthreads array in order to stop them */
1431 if (linuxthreads_breakpoints_inserted
)
1432 update_stop_threads (rpid
);
1435 else if (rpid
!= inferior_pid
)
1438 store_waitstatus (ourstatus
, status
);
1440 if (linuxthreads_attach_pending
&& !stop_soon_quietly
)
1443 target_write_memory (linuxthreads_debug
, (char *)&on
, sizeof (on
));
1444 update_stop_threads (rpid
);
1445 linuxthreads_attach_pending
= 0;
1448 if (linuxthreads_breakpoints_inserted
1449 && WIFSTOPPED(status
)
1450 && WSTOPSIG(status
) == SIGTRAP
)
1451 linuxthreads_breakpoint_pid
= rpid
;
1452 else if (linuxthreads_breakpoint_pid
)
1453 linuxthreads_breakpoint_pid
= 0;
1459 /* Fork an inferior process, and start debugging it with ptrace. */
1462 linuxthreads_create_inferior (exec_file
, allargs
, env
)
1467 if (!exec_file
&& !exec_bfd
)
1469 error ("No executable file specified.\n\
1470 Use the \"file\" or \"exec-file\" command.");
1474 push_target (&linuxthreads_ops
);
1475 linuxthreads_breakpoints_inserted
= 1;
1476 linuxthreads_breakpoint_last
= -1;
1477 linuxthreads_wait_last
= -1;
1478 linuxthreads_exit_status
= __W_STOPCODE(0);
1480 if (linuxthreads_max
)
1481 linuxthreads_attach_pending
= 1;
1483 child_ops
.to_create_inferior (exec_file
, allargs
, env
);
1486 /* Clean up after the inferior dies. */
1489 linuxthreads_mourn_inferior ()
1491 if (linuxthreads_max
)
1494 target_write_memory (linuxthreads_debug
, (char *)&off
, sizeof (off
));
1496 linuxthreads_inferior_pid
= 0;
1497 linuxthreads_breakpoint_pid
= 0;
1498 linuxthreads_step_pid
= 0;
1499 linuxthreads_step_signo
= TARGET_SIGNAL_0
;
1500 linuxthreads_manager_pid
= 0;
1501 linuxthreads_initial_pid
= 0;
1502 linuxthreads_attach_pending
= 0;
1503 init_thread_list(); /* Destroy thread info */
1506 child_ops
.to_mourn_inferior ();
1508 unpush_target (&linuxthreads_ops
);
1511 /* Kill the inferior process */
1514 linuxthreads_kill ()
1519 if (inferior_pid
== 0)
1522 if (linuxthreads_max
&& linuxthreads_manager_pid
!= 0)
1524 /* Remove all threads status. */
1525 inferior_pid
= linuxthreads_manager_pid
;
1526 iterate_active_threads (kill_thread
, 1);
1529 kill_thread (inferior_pid
);
1532 /* doing_quit_force solves a real problem, but I think a properly
1533 placed call to catch_errors would do the trick much more cleanly. */
1534 if (doing_quit_force
>= 0)
1536 if (linuxthreads_max
&& linuxthreads_manager_pid
!= 0)
1538 /* Wait for thread to complete */
1539 while ((rpid
= waitpid (-1, &status
, __WCLONE
)) > 0)
1540 if (!WIFEXITED(status
))
1543 while ((rpid
= waitpid (-1, &status
, 0)) > 0)
1544 if (!WIFEXITED(status
))
1548 while ((rpid
= waitpid (inferior_pid
, &status
, 0)) > 0)
1549 if (!WIFEXITED(status
))
1550 ptrace (PT_KILL
, inferior_pid
, (PTRACE_ARG3_TYPE
) 0, 0);
1554 /* Wait for all threads. */
1556 rpid
= waitpid (-1, &status
, __WCLONE
| WNOHANG
);
1557 while (rpid
> 0 || errno
== EINTR
);
1560 rpid
= waitpid (-1, &status
, WNOHANG
);
1561 while (rpid
> 0 || errno
== EINTR
);
1563 linuxthreads_mourn_inferior ();
1566 /* Insert a breakpoint */
1569 linuxthreads_insert_breakpoint (addr
, contents_cache
)
1571 char *contents_cache
;
1573 if (linuxthreads_max
&& linuxthreads_manager_pid
!= 0)
1575 linuxthreads_breakpoint_addr
= addr
;
1576 iterate_active_threads (insert_breakpoint
, 1);
1577 insert_breakpoint (linuxthreads_manager_pid
);
1580 return child_ops
.to_insert_breakpoint (addr
, contents_cache
);
1583 /* Remove a breakpoint */
1586 linuxthreads_remove_breakpoint (addr
, contents_cache
)
1588 char *contents_cache
;
1590 if (linuxthreads_max
&& linuxthreads_manager_pid
!= 0)
1592 linuxthreads_breakpoint_addr
= addr
;
1593 iterate_active_threads (remove_breakpoint
, 1);
1594 remove_breakpoint (linuxthreads_manager_pid
);
1597 return child_ops
.to_remove_breakpoint (addr
, contents_cache
);
1600 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
1603 linuxthreads_can_run ()
1605 return child_suppress_run
;
1609 init_linuxthreads_ops ()
1611 linuxthreads_ops
.to_shortname
= "linuxthreads";
1612 linuxthreads_ops
.to_longname
= "LINUX threads and pthread.";
1613 linuxthreads_ops
.to_doc
= "LINUX threads and pthread support.";
1614 linuxthreads_ops
.to_attach
= linuxthreads_attach
;
1615 linuxthreads_ops
.to_detach
= linuxthreads_detach
;
1616 linuxthreads_ops
.to_resume
= linuxthreads_resume
;
1617 linuxthreads_ops
.to_wait
= linuxthreads_wait
;
1618 linuxthreads_ops
.to_kill
= linuxthreads_kill
;
1619 linuxthreads_ops
.to_can_run
= linuxthreads_can_run
;
1620 linuxthreads_ops
.to_stratum
= thread_stratum
;
1621 linuxthreads_ops
.to_insert_breakpoint
= linuxthreads_insert_breakpoint
;
1622 linuxthreads_ops
.to_remove_breakpoint
= linuxthreads_remove_breakpoint
;
1623 linuxthreads_ops
.to_create_inferior
= linuxthreads_create_inferior
;
1624 linuxthreads_ops
.to_mourn_inferior
= linuxthreads_mourn_inferior
;
1625 linuxthreads_ops
.to_thread_alive
= linuxthreads_thread_alive
;
1626 linuxthreads_ops
.to_magic
= OPS_MAGIC
;
1630 _initialize_linuxthreads ()
1632 struct sigaction sact
;
1634 init_linuxthreads_ops ();
1635 add_target (&linuxthreads_ops
);
1636 child_suppress_run
= 1;
1638 /* Attach SIGCHLD handler */
1639 sact
.sa_handler
= sigchld_handler
;
1640 sigemptyset (&sact
.sa_mask
);
1642 sigaction (SIGCHLD
, &sact
, NULL
);
1644 /* initialize SIGCHLD mask */
1645 sigemptyset (&linuxthreads_wait_mask
);
1646 sigaddset (&linuxthreads_wait_mask
, SIGCHLD
);