Commit | Line | Data |
---|---|---|
fb0e1ba7 | 1 | /* Multi-threaded debugging support for Linux (LWP layer). |
4e052eda | 2 | Copyright 2000, 2001 Free Software Foundation, Inc. |
fb0e1ba7 MK |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "defs.h" | |
22 | ||
23 | #include "gdb_assert.h" | |
24 | #include <errno.h> | |
25 | #include <signal.h> | |
26 | #include <sys/ptrace.h> | |
27 | #include "gdb_wait.h" | |
28 | ||
29 | #include "gdbthread.h" | |
30 | #include "inferior.h" | |
31 | #include "target.h" | |
4e052eda | 32 | #include "regcache.h" |
7ca673cd | 33 | #include "gdbcmd.h" |
fb0e1ba7 | 34 | |
7ca673cd | 35 | static int debug_lin_lwp; |
fb0e1ba7 | 36 | extern const char *strsignal (int sig); |
fb0e1ba7 MK |
37 | |
38 | /* On Linux there are no real LWP's. The closest thing to LWP's are | |
39 | processes sharing the same VM space. A multi-threaded process is | |
40 | basically a group of such processes. However, such a grouping is | |
41 | almost entirely a user-space issue; the kernel doesn't enforce such | |
42 | a grouping at all (this might change in the future). In general, | |
43 | we'll rely on the threads library (i.e. the LinuxThreads library) | |
44 | to provide such a grouping. | |
45 | ||
46 | It is perfectly well possible to write a multi-threaded application | |
47 | without the assistance of a threads library, by using the clone | |
48 | system call directly. This module should be able to give some | |
49 | rudimentary support for debugging such applications if developers | |
50 | specify the CLONE_PTRACE flag in the clone system call, and are | |
51 | using Linux 2.4 or above. | |
52 | ||
53 | Note that there are some peculiarities in Linux that affect this | |
54 | code: | |
55 | ||
56 | - In general one should specify the __WCLONE flag to waitpid in | |
3f07c44b MK |
57 | order to make it report events for any of the cloned processes |
58 | (and leave it out for the initial process). However, if a cloned | |
59 | process has exited the exit status is only reported if the | |
60 | __WCLONE flag is absent. Linux 2.4 has a __WALL flag, but we | |
61 | cannot use it since GDB must work on older systems too. | |
fb0e1ba7 MK |
62 | |
63 | - When a traced, cloned process exits and is waited for by the | |
4c8de859 | 64 | debugger, the kernel reassigns it to the original parent and |
fb0e1ba7 MK |
65 | keeps it around as a "zombie". Somehow, the LinuxThreads library |
66 | doesn't notice this, which leads to the "zombie problem": When | |
67 | debugged a multi-threaded process that spawns a lot of threads | |
68 | will run out of processes, even if the threads exit, because the | |
69 | "zombies" stay around. */ | |
70 | ||
71 | /* Structure describing a LWP. */ | |
72 | struct lwp_info | |
73 | { | |
74 | /* The process id of the LWP. This is a combination of the LWP id | |
75 | and overall process id. */ | |
39f77062 | 76 | ptid_t ptid; |
fb0e1ba7 MK |
77 | |
78 | /* Non-zero if we sent this LWP a SIGSTOP (but the LWP didn't report | |
79 | it back yet). */ | |
80 | int signalled; | |
81 | ||
82 | /* Non-zero if this LWP is stopped. */ | |
83 | int stopped; | |
84 | ||
85 | /* If non-zero, a pending wait status. */ | |
86 | int status; | |
87 | ||
88 | /* Non-zero if we were stepping this LWP. */ | |
89 | int step; | |
90 | ||
91 | /* Next LWP in list. */ | |
92 | struct lwp_info *next; | |
93 | }; | |
94 | ||
95 | /* List of known LWPs. */ | |
96 | static struct lwp_info *lwp_list; | |
97 | ||
98 | /* Number of LWPs in the list. */ | |
99 | static int num_lwps; | |
100 | ||
101 | /* Non-zero if we're running in "threaded" mode. */ | |
102 | static int threaded; | |
103 | \f | |
104 | ||
ca6724c1 KB |
105 | #define GET_LWP(ptid) ptid_get_lwp (ptid) |
106 | #define GET_PID(ptid) ptid_get_pid (ptid) | |
107 | #define is_lwp(ptid) (GET_LWP (ptid) != 0) | |
108 | #define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) | |
fb0e1ba7 MK |
109 | |
110 | #define is_cloned(pid) (GET_LWP (pid) != GET_PID (pid)) | |
111 | ||
112 | /* If the last reported event was a SIGTRAP, this variable is set to | |
113 | the process id of the LWP/thread that got it. */ | |
39f77062 | 114 | ptid_t trap_ptid; |
fb0e1ba7 MK |
115 | \f |
116 | ||
117 | /* This module's target-specific operations. */ | |
118 | static struct target_ops lin_lwp_ops; | |
119 | ||
120 | /* The standard child operations. */ | |
121 | extern struct target_ops child_ops; | |
122 | ||
3f07c44b MK |
123 | /* Since we cannot wait (in lin_lwp_wait) for the initial process and |
124 | any cloned processes with a single call to waitpid, we have to use | |
4c8de859 | 125 | the WNOHANG flag and call waitpid in a loop. To optimize |
3f07c44b MK |
126 | things a bit we use `sigsuspend' to wake us up when a process has |
127 | something to report (it will send us a SIGCHLD if it has). To make | |
128 | this work we have to juggle with the signal mask. We save the | |
4c8de859 | 129 | original signal mask such that we can restore it before creating a |
3f07c44b MK |
130 | new process in order to avoid blocking certain signals in the |
131 | inferior. We then block SIGCHLD during the waitpid/sigsuspend | |
132 | loop. */ | |
133 | ||
4c8de859 | 134 | /* Original signal mask. */ |
3f07c44b MK |
135 | static sigset_t normal_mask; |
136 | ||
fb0e1ba7 MK |
137 | /* Signal mask for use with sigsuspend in lin_lwp_wait, initialized in |
138 | _initialize_lin_lwp. */ | |
139 | static sigset_t suspend_mask; | |
3f07c44b MK |
140 | |
141 | /* Signals to block to make that sigsuspend work. */ | |
142 | static sigset_t blocked_mask; | |
fb0e1ba7 MK |
143 | \f |
144 | ||
145 | /* Prototypes for local functions. */ | |
c194fbe1 | 146 | static int stop_wait_callback (struct lwp_info *lp, void *data); |
fb0e1ba7 MK |
147 | \f |
148 | ||
c194fbe1 MK |
149 | /* Initialize the list of LWPs. Note that this module, contrary to |
150 | what GDB's generic threads layer does for its thread list, | |
151 | re-initializes the LWP lists whenever we mourn or detach (which | |
152 | doesn't involve mourning) the inferior. */ | |
fb0e1ba7 MK |
153 | |
154 | static void | |
155 | init_lwp_list (void) | |
156 | { | |
157 | struct lwp_info *lp, *lpnext; | |
158 | ||
159 | for (lp = lwp_list; lp; lp = lpnext) | |
160 | { | |
161 | lpnext = lp->next; | |
b8c9b27d | 162 | xfree (lp); |
fb0e1ba7 MK |
163 | } |
164 | ||
165 | lwp_list = NULL; | |
166 | num_lwps = 0; | |
167 | threaded = 0; | |
168 | } | |
169 | ||
170 | /* Add the LWP specified by PID to the list. If this causes the | |
171 | number of LWPs to become larger than one, go into "threaded" mode. | |
172 | Return a pointer to the structure describing the new LWP. */ | |
173 | ||
174 | static struct lwp_info * | |
39f77062 | 175 | add_lwp (ptid_t ptid) |
fb0e1ba7 MK |
176 | { |
177 | struct lwp_info *lp; | |
178 | ||
39f77062 | 179 | gdb_assert (is_lwp (ptid)); |
fb0e1ba7 MK |
180 | |
181 | lp = (struct lwp_info *) xmalloc (sizeof (struct lwp_info)); | |
182 | ||
183 | memset (lp, 0, sizeof (struct lwp_info)); | |
184 | ||
39f77062 | 185 | lp->ptid = ptid; |
fb0e1ba7 MK |
186 | |
187 | lp->next = lwp_list; | |
188 | lwp_list = lp; | |
189 | if (++num_lwps > 1) | |
190 | threaded = 1; | |
191 | ||
192 | return lp; | |
193 | } | |
194 | ||
195 | /* Remove the LWP specified by PID from the list. */ | |
196 | ||
197 | static void | |
39f77062 | 198 | delete_lwp (ptid_t ptid) |
fb0e1ba7 MK |
199 | { |
200 | struct lwp_info *lp, *lpprev; | |
201 | ||
202 | lpprev = NULL; | |
203 | ||
204 | for (lp = lwp_list; lp; lpprev = lp, lp = lp->next) | |
39f77062 | 205 | if (ptid_equal (lp->ptid, ptid)) |
fb0e1ba7 MK |
206 | break; |
207 | ||
208 | if (!lp) | |
209 | return; | |
210 | ||
211 | /* We don't go back to "non-threaded" mode if the number of threads | |
212 | becomes less than two. */ | |
213 | num_lwps--; | |
214 | ||
215 | if (lpprev) | |
216 | lpprev->next = lp->next; | |
217 | else | |
218 | lwp_list = lp->next; | |
219 | ||
b8c9b27d | 220 | xfree (lp); |
fb0e1ba7 MK |
221 | } |
222 | ||
223 | /* Return a pointer to the structure describing the LWP corresponding | |
224 | to PID. If no corresponding LWP could be found, return NULL. */ | |
225 | ||
226 | static struct lwp_info * | |
39f77062 | 227 | find_lwp_pid (ptid_t ptid) |
fb0e1ba7 MK |
228 | { |
229 | struct lwp_info *lp; | |
39f77062 | 230 | int lwp; |
fb0e1ba7 | 231 | |
39f77062 KB |
232 | if (is_lwp (ptid)) |
233 | lwp = GET_LWP (ptid); | |
234 | else | |
235 | lwp = GET_PID (ptid); | |
fb0e1ba7 MK |
236 | |
237 | for (lp = lwp_list; lp; lp = lp->next) | |
39f77062 | 238 | if (lwp == GET_LWP (lp->ptid)) |
fb0e1ba7 MK |
239 | return lp; |
240 | ||
241 | return NULL; | |
242 | } | |
243 | ||
244 | /* Call CALLBACK with its second argument set to DATA for every LWP in | |
245 | the list. If CALLBACK returns 1 for a particular LWP, return a | |
246 | pointer to the structure describing that LWP immediately. | |
247 | Otherwise return NULL. */ | |
248 | ||
249 | struct lwp_info * | |
250 | iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data) | |
251 | { | |
252 | struct lwp_info *lp; | |
253 | ||
254 | for (lp = lwp_list; lp; lp = lp->next) | |
255 | if ((*callback) (lp, data)) | |
256 | return lp; | |
257 | ||
258 | return NULL; | |
259 | } | |
260 | \f | |
261 | ||
e02bc4cc DS |
262 | /* Implementation of the PREPARE_TO_PROCEED hook for the Linux LWP |
263 | layer. | |
264 | ||
265 | Note that this implementation is potentially redundant now that | |
266 | default_prepare_to_proceed() has been added. */ | |
fb0e1ba7 MK |
267 | |
268 | int | |
269 | lin_lwp_prepare_to_proceed (void) | |
270 | { | |
39f77062 KB |
271 | if (! ptid_equal (trap_ptid, null_ptid) |
272 | && ! ptid_equal (inferior_ptid, trap_ptid)) | |
fb0e1ba7 MK |
273 | { |
274 | /* Switched over from TRAP_PID. */ | |
275 | CORE_ADDR stop_pc = read_pc (); | |
276 | CORE_ADDR trap_pc; | |
277 | ||
278 | /* Avoid switching where it wouldn't do any good, i.e. if both | |
279 | threads are at the same breakpoint. */ | |
39f77062 | 280 | trap_pc = read_pc_pid (trap_ptid); |
fb0e1ba7 MK |
281 | if (trap_pc != stop_pc && breakpoint_here_p (trap_pc)) |
282 | { | |
283 | /* User hasn't deleted the breakpoint. Return non-zero, and | |
284 | switch back to TRAP_PID. */ | |
39f77062 | 285 | inferior_ptid = trap_ptid; |
fb0e1ba7 MK |
286 | |
287 | /* FIXME: Is this stuff really necessary? */ | |
288 | flush_cached_frames (); | |
289 | registers_changed (); | |
290 | ||
291 | return 1; | |
292 | } | |
293 | } | |
294 | ||
295 | return 0; | |
296 | } | |
297 | \f | |
298 | ||
299 | #if 0 | |
300 | static void | |
301 | lin_lwp_open (char *args, int from_tty) | |
302 | { | |
303 | push_target (&lin_lwp_ops); | |
304 | } | |
305 | #endif | |
306 | ||
307 | /* Attach to the LWP specified by PID. If VERBOSE is non-zero, print | |
308 | a message telling the user that a new LWP has been added to the | |
309 | process. */ | |
310 | ||
311 | void | |
39f77062 | 312 | lin_lwp_attach_lwp (ptid_t ptid, int verbose) |
fb0e1ba7 MK |
313 | { |
314 | struct lwp_info *lp; | |
315 | ||
39f77062 | 316 | gdb_assert (is_lwp (ptid)); |
fb0e1ba7 MK |
317 | |
318 | if (verbose) | |
39f77062 | 319 | printf_filtered ("[New %s]\n", target_pid_to_str (ptid)); |
fb0e1ba7 | 320 | |
c194fbe1 MK |
321 | /* We assume that we're already tracing the initial process. */ |
322 | if (is_cloned (ptid) && ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0) | |
39f77062 | 323 | error ("Can't attach %s: %s", target_pid_to_str (ptid), strerror (errno)); |
fb0e1ba7 | 324 | |
c194fbe1 MK |
325 | lp = find_lwp_pid (ptid); |
326 | if (lp == NULL) | |
327 | lp = add_lwp (ptid); | |
328 | ||
329 | if (is_cloned (ptid)) | |
330 | lp->signalled = 1; | |
fb0e1ba7 MK |
331 | } |
332 | ||
333 | static void | |
334 | lin_lwp_attach (char *args, int from_tty) | |
335 | { | |
c194fbe1 MK |
336 | struct lwp_info *lp; |
337 | ||
fb0e1ba7 MK |
338 | /* FIXME: We should probably accept a list of process id's, and |
339 | attach all of them. */ | |
c194fbe1 MK |
340 | child_ops.to_attach (args, from_tty); |
341 | ||
342 | /* Add the initial process as the first LWP to the list. */ | |
01263b57 | 343 | lp = add_lwp (BUILD_LWP (PIDGET (inferior_ptid), PIDGET (inferior_ptid))); |
c194fbe1 MK |
344 | |
345 | /* Make sure the initial process is stopped. The user-level threads | |
346 | layer might want to poke around in the inferior, and that won't | |
347 | work if things haven't stabilized yet. */ | |
348 | lp->signalled = 1; | |
349 | stop_wait_callback (lp, NULL); | |
350 | gdb_assert (lp->status == 0); | |
351 | ||
352 | /* Fake the SIGSTOP that core GDB expects. */ | |
353 | lp->status = W_STOPCODE (SIGSTOP); | |
354 | } | |
355 | ||
356 | static int | |
357 | detach_callback (struct lwp_info *lp, void *data) | |
358 | { | |
359 | gdb_assert (lp->status == 0 || WIFSTOPPED (lp->status)); | |
360 | ||
361 | if (debug_lin_lwp && lp->status) | |
b08cfdb6 | 362 | fprintf_unfiltered (gdb_stdlog, "Pending %s for LWP %ld on detach.\n", |
c194fbe1 MK |
363 | strsignal (WSTOPSIG (lp->status)), GET_LWP (lp->ptid)); |
364 | ||
365 | while (lp->signalled && lp->stopped) | |
366 | { | |
367 | if (ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, | |
368 | WSTOPSIG (lp->status)) < 0) | |
369 | error ("Can't continue %s: %s", target_pid_to_str (lp->ptid), | |
370 | strerror (errno)); | |
371 | ||
372 | lp->stopped = 0; | |
373 | lp->status = 0; | |
374 | stop_wait_callback (lp, NULL); | |
375 | ||
376 | gdb_assert (lp->status == 0 || WIFSTOPPED (lp->status)); | |
377 | } | |
378 | ||
379 | if (is_cloned (lp->ptid)) | |
380 | { | |
381 | if (ptrace (PTRACE_DETACH, GET_LWP (lp->ptid), 0, | |
382 | WSTOPSIG (lp->status)) < 0) | |
383 | error ("Can't detach %s: %s", target_pid_to_str (lp->ptid), | |
384 | strerror (errno)); | |
385 | ||
386 | delete_lwp (lp->ptid); | |
387 | } | |
388 | ||
389 | return 0; | |
fb0e1ba7 MK |
390 | } |
391 | ||
392 | static void | |
393 | lin_lwp_detach (char *args, int from_tty) | |
394 | { | |
c194fbe1 MK |
395 | iterate_over_lwps (detach_callback, NULL); |
396 | ||
397 | /* Only the initial (uncloned) process should be left right now. */ | |
398 | gdb_assert (num_lwps == 1); | |
399 | ||
400 | trap_ptid = null_ptid; | |
401 | ||
402 | /* Destroy LWP info; it's no longer valid. */ | |
403 | init_lwp_list (); | |
404 | ||
405 | /* Restore the original signal mask. */ | |
406 | sigprocmask (SIG_SETMASK, &normal_mask, NULL); | |
407 | sigemptyset (&blocked_mask); | |
408 | ||
01263b57 | 409 | inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid)); |
c194fbe1 | 410 | child_ops.to_detach (args, from_tty); |
fb0e1ba7 MK |
411 | } |
412 | \f | |
413 | ||
414 | struct private_thread_info | |
415 | { | |
416 | int lwpid; | |
417 | }; | |
418 | ||
419 | /* Return non-zero if TP corresponds to the LWP specified by DATA | |
420 | (which is assumed to be a pointer to a `struct lwp_info'. */ | |
421 | ||
422 | static int | |
423 | find_lwp_callback (struct thread_info *tp, void *data) | |
424 | { | |
425 | struct lwp_info *lp = data; | |
426 | ||
39f77062 | 427 | if (tp->private->lwpid == GET_LWP (lp->ptid)) |
fb0e1ba7 MK |
428 | return 1; |
429 | ||
430 | return 0; | |
431 | } | |
432 | ||
433 | /* Resume LP. */ | |
434 | ||
435 | static int | |
436 | resume_callback (struct lwp_info *lp, void *data) | |
437 | { | |
438 | if (lp->stopped && lp->status == 0) | |
439 | { | |
440 | struct thread_info *tp; | |
441 | ||
442 | #if 1 | |
443 | /* FIXME: kettenis/2000-08-26: This should really be handled | |
444 | properly by core GDB. */ | |
445 | ||
39f77062 | 446 | tp = find_thread_pid (lp->ptid); |
fb0e1ba7 MK |
447 | if (tp == NULL) |
448 | tp = iterate_over_threads (find_lwp_callback, lp); | |
449 | gdb_assert (tp); | |
450 | ||
451 | /* If we were previously stepping the thread, and now continue | |
452 | the thread we must invalidate the stepping range. However, | |
453 | if there is a step_resume breakpoint for this thread, we must | |
454 | preserve the stepping range to make it possible to continue | |
455 | stepping once we hit it. */ | |
456 | if (tp->step_range_end && tp->step_resume_breakpoint == NULL) | |
457 | { | |
458 | gdb_assert (lp->step); | |
459 | tp->step_range_start = tp->step_range_end = 0; | |
460 | } | |
461 | #endif | |
462 | ||
39f77062 | 463 | child_resume (pid_to_ptid (GET_LWP (lp->ptid)), 0, TARGET_SIGNAL_0); |
fb0e1ba7 MK |
464 | lp->stopped = 0; |
465 | lp->step = 0; | |
466 | } | |
467 | ||
468 | return 0; | |
469 | } | |
470 | ||
471 | static void | |
39f77062 | 472 | lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo) |
fb0e1ba7 MK |
473 | { |
474 | struct lwp_info *lp; | |
475 | int resume_all; | |
476 | ||
477 | /* Apparently the interpretation of PID is dependent on STEP: If | |
478 | STEP is non-zero, a specific PID means `step only this process | |
479 | id'. But if STEP is zero, then PID means `continue *all* | |
480 | processes, but give the signal only to this one'. */ | |
39f77062 | 481 | resume_all = (PIDGET (ptid) == -1) || !step; |
fb0e1ba7 MK |
482 | |
483 | /* If PID is -1, it's the current inferior that should be | |
484 | handled special. */ | |
39f77062 KB |
485 | if (PIDGET (ptid) == -1) |
486 | ptid = inferior_ptid; | |
fb0e1ba7 | 487 | |
39f77062 | 488 | lp = find_lwp_pid (ptid); |
fb0e1ba7 MK |
489 | if (lp) |
490 | { | |
39f77062 | 491 | ptid = pid_to_ptid (GET_LWP (lp->ptid)); |
fb0e1ba7 | 492 | |
fb0e1ba7 MK |
493 | /* Remember if we're stepping. */ |
494 | lp->step = step; | |
495 | ||
496 | /* If we have a pending wait status for this thread, there is no | |
497 | point in resuming the process. */ | |
498 | if (lp->status) | |
499 | { | |
500 | /* FIXME: What should we do if we are supposed to continue | |
501 | this thread with a signal? */ | |
502 | gdb_assert (signo == TARGET_SIGNAL_0); | |
503 | return; | |
504 | } | |
40564aca MK |
505 | |
506 | /* Mark LWP as not stopped to prevent it from being continued by | |
507 | resume_callback. */ | |
508 | lp->stopped = 0; | |
fb0e1ba7 MK |
509 | } |
510 | ||
511 | if (resume_all) | |
512 | iterate_over_lwps (resume_callback, NULL); | |
513 | ||
39f77062 | 514 | child_resume (ptid, step, signo); |
fb0e1ba7 MK |
515 | } |
516 | \f | |
517 | ||
518 | /* Send a SIGSTOP to LP. */ | |
519 | ||
520 | static int | |
521 | stop_callback (struct lwp_info *lp, void *data) | |
522 | { | |
523 | if (! lp->stopped && ! lp->signalled) | |
524 | { | |
525 | int ret; | |
526 | ||
39f77062 | 527 | ret = kill (GET_LWP (lp->ptid), SIGSTOP); |
fb0e1ba7 MK |
528 | gdb_assert (ret == 0); |
529 | ||
530 | lp->signalled = 1; | |
531 | gdb_assert (lp->status == 0); | |
532 | } | |
533 | ||
534 | return 0; | |
535 | } | |
536 | ||
537 | /* Wait until LP is stopped. */ | |
538 | ||
539 | static int | |
540 | stop_wait_callback (struct lwp_info *lp, void *data) | |
541 | { | |
542 | if (! lp->stopped && lp->signalled) | |
543 | { | |
544 | pid_t pid; | |
545 | int status; | |
546 | ||
547 | gdb_assert (lp->status == 0); | |
548 | ||
39f77062 KB |
549 | pid = waitpid (GET_LWP (lp->ptid), &status, |
550 | is_cloned (lp->ptid) ? __WCLONE : 0); | |
fb0e1ba7 MK |
551 | if (pid == -1 && errno == ECHILD) |
552 | /* OK, the proccess has disappeared. We'll catch the actual | |
3f07c44b | 553 | exit event in lin_lwp_wait. */ |
fb0e1ba7 MK |
554 | return 0; |
555 | ||
39f77062 | 556 | gdb_assert (pid == GET_LWP (lp->ptid)); |
fb0e1ba7 MK |
557 | |
558 | if (WIFEXITED (status) || WIFSIGNALED (status)) | |
559 | { | |
560 | gdb_assert (num_lwps > 1); | |
fb0e1ba7 | 561 | |
39f77062 | 562 | if (in_thread_list (lp->ptid)) |
e6328671 MK |
563 | { |
564 | /* Core GDB cannot deal with us deleting the current | |
565 | thread. */ | |
39f77062 KB |
566 | if (!ptid_equal (lp->ptid, inferior_ptid)) |
567 | delete_thread (lp->ptid); | |
e6328671 | 568 | printf_unfiltered ("[%s exited]\n", |
39f77062 | 569 | target_pid_to_str (lp->ptid)); |
e6328671 | 570 | } |
7ca673cd | 571 | if (debug_lin_lwp) |
9085700c | 572 | fprintf_unfiltered (gdb_stdlog, |
39f77062 | 573 | "%s exited.\n", target_pid_to_str (lp->ptid)); |
7ca673cd | 574 | |
39f77062 | 575 | delete_lwp (lp->ptid); |
fb0e1ba7 MK |
576 | return 0; |
577 | } | |
578 | ||
579 | gdb_assert (WIFSTOPPED (status)); | |
580 | lp->stopped = 1; | |
581 | ||
582 | if (WSTOPSIG (status) != SIGSTOP) | |
583 | { | |
584 | if (WSTOPSIG (status) == SIGTRAP | |
39f77062 | 585 | && breakpoint_inserted_here_p (read_pc_pid (pid_to_ptid (pid)) |
fb0e1ba7 MK |
586 | - DECR_PC_AFTER_BREAK)) |
587 | { | |
588 | /* If a LWP other than the LWP that we're reporting an | |
589 | event for has hit a GDB breakpoint (as opposed to | |
590 | some random trap signal), then just arrange for it to | |
591 | hit it again later. We don't keep the SIGTRAP status | |
592 | and don't forward the SIGTRAP signal to the LWP. We | |
593 | will handle the current event, eventually we will | |
594 | resume all LWPs, and this one will get its breakpoint | |
595 | trap again. | |
596 | ||
597 | If we do not do this, then we run the risk that the | |
598 | user will delete or disable the breakpoint, but the | |
599 | thread will have already tripped on it. */ | |
7ca673cd MS |
600 | |
601 | if (debug_lin_lwp) | |
9085700c MS |
602 | fprintf_unfiltered (gdb_stdlog, |
603 | "Tripped breakpoint at %lx in LWP %d" | |
604 | " while waiting for SIGSTOP.\n", | |
39f77062 | 605 | (long) read_pc_pid (lp->ptid), pid); |
7ca673cd | 606 | |
fb0e1ba7 MK |
607 | /* Set the PC to before the trap. */ |
608 | if (DECR_PC_AFTER_BREAK) | |
39f77062 KB |
609 | write_pc_pid (read_pc_pid (pid_to_ptid (pid)) |
610 | - DECR_PC_AFTER_BREAK, | |
611 | pid_to_ptid (pid)); | |
fb0e1ba7 MK |
612 | } |
613 | else | |
614 | { | |
7ca673cd | 615 | if (debug_lin_lwp) |
9085700c MS |
616 | fprintf_unfiltered (gdb_stdlog, |
617 | "Received %s in LWP %d while waiting for SIGSTOP.\n", | |
618 | strsignal (WSTOPSIG (status)), pid); | |
7ca673cd | 619 | |
fb0e1ba7 MK |
620 | /* The thread was stopped with a signal other than |
621 | SIGSTOP, and didn't accidentiliy trip a breakpoint. | |
622 | Record the wait status. */ | |
623 | lp->status = status; | |
624 | } | |
625 | } | |
626 | else | |
627 | { | |
628 | /* We caught the SIGSTOP that we intended to catch, so | |
629 | there's no SIGSTOP pending. */ | |
630 | lp->signalled = 0; | |
631 | } | |
632 | } | |
633 | ||
634 | return 0; | |
635 | } | |
636 | ||
637 | /* Return non-zero if LP has a wait status pending. */ | |
638 | ||
639 | static int | |
640 | status_callback (struct lwp_info *lp, void *data) | |
641 | { | |
642 | return (lp->status != 0); | |
643 | } | |
644 | ||
645 | /* Return non-zero if LP isn't stopped. */ | |
646 | ||
647 | static int | |
648 | running_callback (struct lwp_info *lp, void *data) | |
649 | { | |
650 | return (lp->stopped == 0); | |
651 | } | |
652 | ||
39f77062 KB |
653 | static ptid_t |
654 | lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus) | |
fb0e1ba7 MK |
655 | { |
656 | struct lwp_info *lp = NULL; | |
657 | int options = 0; | |
658 | int status = 0; | |
39f77062 | 659 | pid_t pid = PIDGET (ptid); |
fb0e1ba7 | 660 | |
3f07c44b MK |
661 | /* Make sure SIGCHLD is blocked. */ |
662 | if (! sigismember (&blocked_mask, SIGCHLD)) | |
663 | { | |
664 | sigaddset (&blocked_mask, SIGCHLD); | |
665 | sigprocmask (SIG_BLOCK, &blocked_mask, NULL); | |
666 | } | |
667 | ||
fb0e1ba7 MK |
668 | retry: |
669 | ||
670 | /* First check if there is a LWP with a wait status pending. */ | |
671 | if (pid == -1) | |
672 | { | |
673 | /* Any LWP will do. */ | |
674 | lp = iterate_over_lwps (status_callback, NULL); | |
675 | if (lp) | |
676 | { | |
7ca673cd | 677 | if (debug_lin_lwp) |
9085700c | 678 | fprintf_unfiltered (gdb_stdlog, |
b08cfdb6 | 679 | "Using pending wait status for LWP %ld.\n", |
3d6e28e2 | 680 | GET_LWP (lp->ptid)); |
7ca673cd | 681 | |
fb0e1ba7 MK |
682 | status = lp->status; |
683 | lp->status = 0; | |
684 | } | |
685 | ||
686 | /* But if we don't fine one, we'll have to wait, and check both | |
687 | cloned and uncloned processes. We start with the cloned | |
688 | processes. */ | |
689 | options = __WCLONE | WNOHANG; | |
690 | } | |
39f77062 | 691 | else if (is_lwp (ptid)) |
fb0e1ba7 | 692 | { |
7ca673cd | 693 | if (debug_lin_lwp) |
9085700c | 694 | fprintf_unfiltered (gdb_stdlog, |
b08cfdb6 | 695 | "Waiting for specific LWP %ld.\n", |
ce696e05 | 696 | GET_LWP (ptid)); |
7ca673cd | 697 | |
fb0e1ba7 | 698 | /* We have a specific LWP to check. */ |
39f77062 | 699 | lp = find_lwp_pid (ptid); |
fb0e1ba7 MK |
700 | gdb_assert (lp); |
701 | status = lp->status; | |
702 | lp->status = 0; | |
7ca673cd MS |
703 | |
704 | if (debug_lin_lwp) | |
705 | if (status) | |
9085700c | 706 | fprintf_unfiltered (gdb_stdlog, |
b08cfdb6 | 707 | "Using pending wait status for LWP %ld.\n", |
39f77062 | 708 | GET_LWP (lp->ptid)); |
fb0e1ba7 MK |
709 | |
710 | /* If we have to wait, take into account whether PID is a cloned | |
711 | process or not. And we have to convert it to something that | |
712 | the layer beneath us can understand. */ | |
39f77062 KB |
713 | options = is_cloned (lp->ptid) ? __WCLONE : 0; |
714 | pid = GET_LWP (ptid); | |
fb0e1ba7 MK |
715 | } |
716 | ||
717 | if (status && lp->signalled) | |
718 | { | |
719 | /* A pending SIGSTOP may interfere with the normal stream of | |
720 | events. In a typical case where interference is a problem, | |
721 | we have a SIGSTOP signal pending for LWP A while | |
722 | single-stepping it, encounter an event in LWP B, and take the | |
723 | pending SIGSTOP while trying to stop LWP A. After processing | |
724 | the event in LWP B, LWP A is continued, and we'll never see | |
725 | the SIGTRAP associated with the last time we were | |
726 | single-stepping LWP A. */ | |
727 | ||
728 | /* Resume the thread. It should halt immediately returning the | |
729 | pending SIGSTOP. */ | |
39f77062 KB |
730 | child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, |
731 | TARGET_SIGNAL_0); | |
fb0e1ba7 MK |
732 | lp->stopped = 0; |
733 | ||
734 | /* This should catch the pending SIGSTOP. */ | |
735 | stop_wait_callback (lp, NULL); | |
736 | } | |
737 | ||
738 | set_sigint_trap (); /* Causes SIGINT to be passed on to the | |
739 | attached process. */ | |
740 | set_sigio_trap (); | |
741 | ||
742 | while (status == 0) | |
743 | { | |
744 | pid_t lwpid; | |
745 | ||
746 | lwpid = waitpid (pid, &status, options); | |
747 | if (lwpid > 0) | |
748 | { | |
749 | gdb_assert (pid == -1 || lwpid == pid); | |
750 | ||
39f77062 | 751 | lp = find_lwp_pid (pid_to_ptid (lwpid)); |
fb0e1ba7 MK |
752 | if (! lp) |
753 | { | |
39f77062 | 754 | lp = add_lwp (BUILD_LWP (lwpid, GET_PID (inferior_ptid))); |
fb0e1ba7 MK |
755 | if (threaded) |
756 | { | |
3f07c44b MK |
757 | gdb_assert (WIFSTOPPED (status) |
758 | && WSTOPSIG (status) == SIGSTOP); | |
fb0e1ba7 MK |
759 | lp->signalled = 1; |
760 | ||
39f77062 | 761 | if (! in_thread_list (inferior_ptid)) |
fb0e1ba7 | 762 | { |
39f77062 KB |
763 | inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), |
764 | GET_PID (inferior_ptid)); | |
765 | add_thread (inferior_ptid); | |
fb0e1ba7 MK |
766 | } |
767 | ||
39f77062 | 768 | add_thread (lp->ptid); |
fb0e1ba7 | 769 | printf_unfiltered ("[New %s]\n", |
39f77062 | 770 | target_pid_to_str (lp->ptid)); |
fb0e1ba7 MK |
771 | } |
772 | } | |
773 | ||
774 | /* Make sure we don't report a TARGET_WAITKIND_EXITED or | |
775 | TARGET_WAITKIND_SIGNALLED event if there are still LWP's | |
776 | left in the process. */ | |
777 | if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1) | |
778 | { | |
39f77062 | 779 | if (in_thread_list (lp->ptid)) |
fb0e1ba7 | 780 | { |
e6328671 | 781 | /* Core GDB cannot deal with us deleting the current |
fb0e1ba7 | 782 | thread. */ |
39f77062 KB |
783 | if (! ptid_equal (lp->ptid, inferior_ptid)) |
784 | delete_thread (lp->ptid); | |
fb0e1ba7 | 785 | printf_unfiltered ("[%s exited]\n", |
39f77062 | 786 | target_pid_to_str (lp->ptid)); |
fb0e1ba7 | 787 | } |
7ca673cd | 788 | if (debug_lin_lwp) |
9085700c MS |
789 | fprintf_unfiltered (gdb_stdlog, |
790 | "%s exited.\n", | |
39f77062 | 791 | target_pid_to_str (lp->ptid)); |
7ca673cd | 792 | |
39f77062 | 793 | delete_lwp (lp->ptid); |
fb0e1ba7 MK |
794 | |
795 | /* Make sure there is at least one thread running. */ | |
796 | gdb_assert (iterate_over_lwps (running_callback, NULL)); | |
797 | ||
798 | /* Discard the event. */ | |
799 | status = 0; | |
800 | continue; | |
801 | } | |
802 | ||
803 | /* Make sure we don't report a SIGSTOP that we sent | |
804 | ourselves in an attempt to stop an LWP. */ | |
805 | if (lp->signalled && WIFSTOPPED (status) | |
806 | && WSTOPSIG (status) == SIGSTOP) | |
807 | { | |
7ca673cd | 808 | if (debug_lin_lwp) |
9085700c MS |
809 | fprintf_unfiltered (gdb_stdlog, |
810 | "Delayed SIGSTOP caught for %s.\n", | |
39f77062 | 811 | target_pid_to_str (lp->ptid)); |
7ca673cd | 812 | |
fb0e1ba7 MK |
813 | /* This is a delayed SIGSTOP. */ |
814 | lp->signalled = 0; | |
815 | ||
39f77062 KB |
816 | child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, |
817 | TARGET_SIGNAL_0); | |
fb0e1ba7 MK |
818 | lp->stopped = 0; |
819 | ||
820 | /* Discard the event. */ | |
821 | status = 0; | |
822 | continue; | |
823 | } | |
824 | ||
825 | break; | |
826 | } | |
827 | ||
828 | if (pid == -1) | |
829 | { | |
830 | /* Alternate between checking cloned and uncloned processes. */ | |
831 | options ^= __WCLONE; | |
832 | ||
833 | /* And suspend every time we have checked both. */ | |
834 | if (options & __WCLONE) | |
835 | sigsuspend (&suspend_mask); | |
836 | } | |
837 | ||
838 | /* We shouldn't end up here unless we want to try again. */ | |
839 | gdb_assert (status == 0); | |
840 | } | |
841 | ||
842 | clear_sigio_trap (); | |
843 | clear_sigint_trap (); | |
844 | ||
845 | gdb_assert (lp); | |
846 | ||
847 | /* Don't report signals that GDB isn't interested in, such as | |
848 | signals that are neither printed nor stopped upon. Stopping all | |
849 | threads can be a bit time-consuming so if we want decent | |
850 | performance with heavily multi-threaded programs, especially when | |
851 | they're using a high frequency timer, we'd better avoid it if we | |
852 | can. */ | |
853 | ||
854 | if (WIFSTOPPED (status)) | |
855 | { | |
856 | int signo = target_signal_from_host (WSTOPSIG (status)); | |
857 | ||
858 | if (signal_stop_state (signo) == 0 | |
859 | && signal_print_state (signo) == 0 | |
860 | && signal_pass_state (signo) == 1) | |
861 | { | |
39f77062 | 862 | child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo); |
fb0e1ba7 MK |
863 | lp->stopped = 0; |
864 | status = 0; | |
865 | goto retry; | |
866 | } | |
867 | } | |
868 | ||
869 | /* This LWP is stopped now. */ | |
870 | lp->stopped = 1; | |
871 | ||
872 | /* Now stop all other LWP's ... */ | |
873 | iterate_over_lwps (stop_callback, NULL); | |
874 | ||
875 | /* ... and wait until all of them have reported back that they're no | |
876 | longer running. */ | |
877 | iterate_over_lwps (stop_wait_callback, NULL); | |
878 | ||
879 | /* If we're not running in "threaded" mode, we'll report the bare | |
880 | process id. */ | |
881 | ||
882 | if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) | |
39f77062 | 883 | trap_ptid = (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid))); |
fb0e1ba7 | 884 | else |
39f77062 | 885 | trap_ptid = null_ptid; |
fb0e1ba7 MK |
886 | |
887 | store_waitstatus (ourstatus, status); | |
39f77062 | 888 | return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid))); |
fb0e1ba7 MK |
889 | } |
890 | ||
891 | static int | |
892 | kill_callback (struct lwp_info *lp, void *data) | |
893 | { | |
39f77062 | 894 | ptrace (PTRACE_KILL, GET_LWP (lp->ptid), 0, 0); |
fb0e1ba7 MK |
895 | return 0; |
896 | } | |
897 | ||
898 | static int | |
899 | kill_wait_callback (struct lwp_info *lp, void *data) | |
900 | { | |
901 | pid_t pid; | |
902 | ||
903 | /* We must make sure that there are no pending events (delayed | |
904 | SIGSTOPs, pending SIGTRAPs, etc.) to make sure the current | |
905 | program doesn't interfere with any following debugging session. */ | |
906 | ||
907 | /* For cloned processes we must check both with __WCLONE and | |
908 | without, since the exit status of a cloned process isn't reported | |
909 | with __WCLONE. */ | |
39f77062 | 910 | if (is_cloned (lp->ptid)) |
fb0e1ba7 MK |
911 | { |
912 | do | |
913 | { | |
39f77062 | 914 | pid = waitpid (GET_LWP (lp->ptid), NULL, __WCLONE); |
fb0e1ba7 | 915 | } |
39f77062 | 916 | while (pid == GET_LWP (lp->ptid)); |
fb0e1ba7 MK |
917 | |
918 | gdb_assert (pid == -1 && errno == ECHILD); | |
919 | } | |
920 | ||
921 | do | |
922 | { | |
39f77062 | 923 | pid = waitpid (GET_LWP (lp->ptid), NULL, 0); |
fb0e1ba7 | 924 | } |
39f77062 | 925 | while (pid == GET_LWP (lp->ptid)); |
fb0e1ba7 MK |
926 | |
927 | gdb_assert (pid == -1 && errno == ECHILD); | |
928 | return 0; | |
929 | } | |
930 | ||
931 | static void | |
932 | lin_lwp_kill (void) | |
933 | { | |
934 | /* Kill all LWP's ... */ | |
935 | iterate_over_lwps (kill_callback, NULL); | |
936 | ||
937 | /* ... and wait until we've flushed all events. */ | |
938 | iterate_over_lwps (kill_wait_callback, NULL); | |
939 | ||
940 | target_mourn_inferior (); | |
941 | } | |
942 | ||
943 | static void | |
944 | lin_lwp_create_inferior (char *exec_file, char *allargs, char **env) | |
945 | { | |
c194fbe1 | 946 | child_ops.to_create_inferior (exec_file, allargs, env); |
fb0e1ba7 MK |
947 | } |
948 | ||
949 | static void | |
950 | lin_lwp_mourn_inferior (void) | |
951 | { | |
c194fbe1 | 952 | trap_ptid = null_ptid; |
fb0e1ba7 | 953 | |
c194fbe1 | 954 | /* Destroy LWP info; it's no longer valid. */ |
fb0e1ba7 MK |
955 | init_lwp_list (); |
956 | ||
4c8de859 | 957 | /* Restore the original signal mask. */ |
3f07c44b MK |
958 | sigprocmask (SIG_SETMASK, &normal_mask, NULL); |
959 | sigemptyset (&blocked_mask); | |
960 | ||
c194fbe1 | 961 | child_ops.to_mourn_inferior (); |
fb0e1ba7 MK |
962 | } |
963 | ||
964 | static void | |
965 | lin_lwp_fetch_registers (int regno) | |
966 | { | |
39f77062 | 967 | struct cleanup *old_chain = save_inferior_ptid (); |
fb0e1ba7 | 968 | |
39f77062 KB |
969 | if (is_lwp (inferior_ptid)) |
970 | inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid)); | |
fb0e1ba7 MK |
971 | |
972 | fetch_inferior_registers (regno); | |
973 | ||
974 | do_cleanups (old_chain); | |
975 | } | |
976 | ||
977 | static void | |
978 | lin_lwp_store_registers (int regno) | |
979 | { | |
39f77062 | 980 | struct cleanup *old_chain = save_inferior_ptid (); |
fb0e1ba7 | 981 | |
39f77062 KB |
982 | if (is_lwp (inferior_ptid)) |
983 | inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid)); | |
fb0e1ba7 MK |
984 | |
985 | store_inferior_registers (regno); | |
986 | ||
987 | do_cleanups (old_chain); | |
988 | } | |
989 | ||
990 | static int | |
991 | lin_lwp_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, | |
e5da8f38 | 992 | struct mem_attrib *attrib, |
fb0e1ba7 MK |
993 | struct target_ops *target) |
994 | { | |
39f77062 | 995 | struct cleanup *old_chain = save_inferior_ptid (); |
fb0e1ba7 MK |
996 | int xfer; |
997 | ||
39f77062 KB |
998 | if (is_lwp (inferior_ptid)) |
999 | inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid)); | |
fb0e1ba7 | 1000 | |
e5da8f38 | 1001 | xfer = child_xfer_memory (memaddr, myaddr, len, write, attrib, target); |
fb0e1ba7 MK |
1002 | |
1003 | do_cleanups (old_chain); | |
1004 | return xfer; | |
1005 | } | |
1006 | ||
1007 | static int | |
39f77062 | 1008 | lin_lwp_thread_alive (ptid_t ptid) |
fb0e1ba7 | 1009 | { |
39f77062 | 1010 | gdb_assert (is_lwp (ptid)); |
fb0e1ba7 MK |
1011 | |
1012 | errno = 0; | |
39f77062 | 1013 | ptrace (PTRACE_PEEKUSER, GET_LWP (ptid), 0, 0); |
fb0e1ba7 MK |
1014 | if (errno) |
1015 | return 0; | |
1016 | ||
1017 | return 1; | |
1018 | } | |
1019 | ||
1020 | static char * | |
39f77062 | 1021 | lin_lwp_pid_to_str (ptid_t ptid) |
fb0e1ba7 MK |
1022 | { |
1023 | static char buf[64]; | |
1024 | ||
39f77062 | 1025 | if (is_lwp (ptid)) |
fb0e1ba7 | 1026 | { |
b08cfdb6 | 1027 | snprintf (buf, sizeof (buf), "LWP %ld", GET_LWP (ptid)); |
fb0e1ba7 MK |
1028 | return buf; |
1029 | } | |
1030 | ||
39f77062 | 1031 | return normal_pid_to_str (ptid); |
fb0e1ba7 MK |
1032 | } |
1033 | ||
1034 | static void | |
1035 | init_lin_lwp_ops (void) | |
1036 | { | |
1037 | #if 0 | |
1038 | lin_lwp_ops.to_open = lin_lwp_open; | |
1039 | #endif | |
1040 | lin_lwp_ops.to_shortname = "lwp-layer"; | |
1041 | lin_lwp_ops.to_longname = "lwp-layer"; | |
1042 | lin_lwp_ops.to_doc = "Low level threads support (LWP layer)"; | |
1043 | lin_lwp_ops.to_attach = lin_lwp_attach; | |
1044 | lin_lwp_ops.to_detach = lin_lwp_detach; | |
1045 | lin_lwp_ops.to_resume = lin_lwp_resume; | |
1046 | lin_lwp_ops.to_wait = lin_lwp_wait; | |
1047 | lin_lwp_ops.to_fetch_registers = lin_lwp_fetch_registers; | |
1048 | lin_lwp_ops.to_store_registers = lin_lwp_store_registers; | |
1049 | lin_lwp_ops.to_xfer_memory = lin_lwp_xfer_memory; | |
1050 | lin_lwp_ops.to_kill = lin_lwp_kill; | |
1051 | lin_lwp_ops.to_create_inferior = lin_lwp_create_inferior; | |
1052 | lin_lwp_ops.to_mourn_inferior = lin_lwp_mourn_inferior; | |
1053 | lin_lwp_ops.to_thread_alive = lin_lwp_thread_alive; | |
1054 | lin_lwp_ops.to_pid_to_str = lin_lwp_pid_to_str; | |
1055 | lin_lwp_ops.to_stratum = thread_stratum; | |
1056 | lin_lwp_ops.to_has_thread_control = tc_schedlock; | |
1057 | lin_lwp_ops.to_magic = OPS_MAGIC; | |
1058 | } | |
1059 | ||
1060 | static void | |
1061 | sigchld_handler (int signo) | |
1062 | { | |
1063 | /* Do nothing. The only reason for this handler is that it allows | |
1064 | us to use sigsuspend in lin_lwp_wait above to wait for the | |
1065 | arrival of a SIGCHLD. */ | |
1066 | } | |
1067 | ||
1068 | void | |
1069 | _initialize_lin_lwp (void) | |
1070 | { | |
1071 | struct sigaction action; | |
fb0e1ba7 MK |
1072 | |
1073 | extern void thread_db_init (struct target_ops *); | |
1074 | ||
1075 | init_lin_lwp_ops (); | |
1076 | add_target (&lin_lwp_ops); | |
1077 | thread_db_init (&lin_lwp_ops); | |
1078 | ||
4c8de859 | 1079 | /* Save the original signal mask. */ |
3f07c44b MK |
1080 | sigprocmask (SIG_SETMASK, NULL, &normal_mask); |
1081 | ||
fb0e1ba7 MK |
1082 | action.sa_handler = sigchld_handler; |
1083 | sigemptyset (&action.sa_mask); | |
1084 | action.sa_flags = 0; | |
1085 | sigaction (SIGCHLD, &action, NULL); | |
1086 | ||
3f07c44b MK |
1087 | /* Make sure we don't block SIGCHLD during a sigsuspend. */ |
1088 | sigprocmask (SIG_SETMASK, NULL, &suspend_mask); | |
fb0e1ba7 | 1089 | sigdelset (&suspend_mask, SIGCHLD); |
3f07c44b MK |
1090 | |
1091 | sigemptyset (&blocked_mask); | |
7ca673cd MS |
1092 | |
1093 | add_show_from_set (add_set_cmd ("lin-lwp", no_class, var_zinteger, | |
1094 | (char *) &debug_lin_lwp, | |
1095 | "Set debugging of linux lwp module.\n\ | |
1096 | Enables printf debugging output.\n", | |
1097 | &setdebuglist), | |
1098 | &showdebuglist); | |
fb0e1ba7 MK |
1099 | } |
1100 | \f | |
1101 | ||
1102 | /* FIXME: kettenis/2000-08-26: The stuff on this page is specific to | |
1103 | the LinuxThreads library and therefore doesn't really belong here. */ | |
1104 | ||
1105 | /* Read variable NAME in the target and return its value if found. | |
1106 | Otherwise return zero. It is assumed that the type of the variable | |
1107 | is `int'. */ | |
1108 | ||
1109 | static int | |
1110 | get_signo (const char *name) | |
1111 | { | |
1112 | struct minimal_symbol *ms; | |
1113 | int signo; | |
1114 | ||
1115 | ms = lookup_minimal_symbol (name, NULL, NULL); | |
1116 | if (ms == NULL) | |
1117 | return 0; | |
1118 | ||
1119 | if (target_read_memory (SYMBOL_VALUE_ADDRESS (ms), (char *) &signo, | |
1120 | sizeof (signo)) != 0) | |
1121 | return 0; | |
1122 | ||
1123 | return signo; | |
1124 | } | |
1125 | ||
1126 | /* Return the set of signals used by the threads library in *SET. */ | |
1127 | ||
1128 | void | |
1129 | lin_thread_get_thread_signals (sigset_t *set) | |
1130 | { | |
3f07c44b MK |
1131 | struct sigaction action; |
1132 | int restart, cancel; | |
fb0e1ba7 MK |
1133 | |
1134 | sigemptyset (set); | |
1135 | ||
1136 | restart = get_signo ("__pthread_sig_restart"); | |
1137 | if (restart == 0) | |
1138 | return; | |
1139 | ||
1140 | cancel = get_signo ("__pthread_sig_cancel"); | |
1141 | if (cancel == 0) | |
1142 | return; | |
1143 | ||
1144 | sigaddset (set, restart); | |
1145 | sigaddset (set, cancel); | |
3f07c44b MK |
1146 | |
1147 | /* The LinuxThreads library makes terminating threads send a special | |
1148 | "cancel" signal instead of SIGCHLD. Make sure we catch those (to | |
1149 | prevent them from terminating GDB itself, which is likely to be | |
1150 | their default action) and treat them the same way as SIGCHLD. */ | |
1151 | ||
1152 | action.sa_handler = sigchld_handler; | |
1153 | sigemptyset (&action.sa_mask); | |
1154 | action.sa_flags = 0; | |
1155 | sigaction (cancel, &action, NULL); | |
1156 | ||
1157 | /* We block the "cancel" signal throughout this code ... */ | |
1158 | sigaddset (&blocked_mask, cancel); | |
1159 | sigprocmask (SIG_BLOCK, &blocked_mask, NULL); | |
1160 | ||
1161 | /* ... except during a sigsuspend. */ | |
1162 | sigdelset (&suspend_mask, cancel); | |
fb0e1ba7 | 1163 | } |