]> git.pld-linux.org Git - packages/gdb.git/blame - gdb-bz592031-siginfo-lost-4of5.patch
- updated (performance fixes).
[packages/gdb.git] / gdb-bz592031-siginfo-lost-4of5.patch
CommitLineData
51a5ef0f
PS
1http://sourceware.org/ml/gdb-patches/2010-09/msg00360.html
2Subject: [patch 3/4]#3 linux-nat: Do not respawn signals
3
4Hi,
5
6linux-nat.c is fixed to never respawn signals; possibly keeping SIGSTOP
7pending, as is done in current in FSF gdbserver and as suggested by Pedro:
8 http://sourceware.org/ml/gdb-patches/2010-08/msg00544.html
9
10The last linux-nat.c removed patch chunk comes from the initial implementation
11by Mark Kettenis:
12 [PATCH] New Linux threads support
13 http://sourceware.org/ml/gdb-patches/2000-09/msg00020.html
14 92280a75e017683bf8e4f339f4f85640b0700509
15It gets in part reimplemented into the new stop_wait_callback <if (lp->step)>
16part and partially just not needed as currently GDB never drops the signals as
17it does not PTRACE_CONT the thread; signal is kept for processing:
18 "RC: Not resuming sibling %s (has pending)\n"
19
20In stop_wait_callback I believe breakpoints cancellation is not needed here,
21it would be done later.
22
23
24The testcase sigstep-threads.exp was written to catch a regression-like
25appearance then the new <if (lp->step)> part of stop_wait_callback gets
26removed. Still the tecase fails even with FSF HEAD:
27
2832 var++; /* step-1 */
29(gdb) step
30Program received signal SIGUSR1, User defined signal 1.
31Program received signal SIGUSR1, User defined signal 1.
3231 { /* step-0 */
33
34There is no reason why it shouldn't stop on line 33, between line 32 and line
3533 no signal would occur. Stepping of the current thread should not be
36affected by whatever happens in the other threads as select_event_lwp has:
37 /* Give preference to any LWP that is being single-stepped. */
38
39There is a problem that with FSF HEAD GDB does PTRACE_SINGLESTEP for thread A,
40PTRACE_CONT for thread B (because of set scheduler-locking off), thread B hits
41SIGUSR1, so GDB tkills thread A with SIGSTOP and it can receive SIGSTOP for
42thread A before the SIGTRAP for completed PTRACE_SINGLESTEP. At that moment
43select_event_lwp. forgets it was stepping thread A because there is no pending
44SIGTRAP event. currently_stepping still remembers thread A was stepping so it
45will later stop but as thread A was PTRACE_CONT-ed in the meantime it is too
46late.
47
48There is the new <if (lp->step)> part of stop_wait_callback to always track
49thread A is stepping. Due to different scheduling without this part the
50changed GDB would very rarely stop in this testcase otherwise, making it look
51as a regression.
52
53I have some another patch I may post separately as if multiple signals happen
54besides SIGTRAP GDB still may switch from thread A away (as not considering it
55stepping) to thread B for SIGUSR and accidentally PTRACE_CONT thread A.
56But I do not find this as a prerequisite for this patchset.
57
58
59
60Thanks,
61Jan
62
63
64gdb/
652010-09-20 Jan Kratochvil <jan.kratochvil@redhat.com>
66
67 * linux-nat.c (stop_wait_callback): New gdb_assert. Remove signals
68 respawning; keep TP with SIGNALLED. New debugging message "SWC:
69 Delayed SIGSTOP caught for %s.". Catch next signal if SIGSTOP has
70 been caught and LP->STEP is set.
71 (linux_nat_wait_1) <lp && lp->signalled>: Remove.
72
73gdb/testsuite/
742010-09-20 Jan Kratochvil <jan.kratochvil@redhat.com>
75
76 * gdb.threads/siginfo-threads.exp: New file.
77 * gdb.threads/siginfo-threads.c: New file.
78 * gdb.threads/sigstep-threads.exp: New file.
79 * gdb.threads/sigstep-threads.c: New file.
80
f412e1b4 81Index: gdb-7.4.50.20111218/gdb/linux-nat.c
51a5ef0f 82===================================================================
f412e1b4
PS
83--- gdb-7.4.50.20111218.orig/gdb/linux-nat.c 2011-12-19 01:25:42.000000000 +0100
84+++ gdb-7.4.50.20111218/gdb/linux-nat.c 2011-12-19 02:17:05.412607735 +0100
85@@ -2843,6 +2843,8 @@ stop_wait_callback (struct lwp_info *lp,
51a5ef0f
PS
86 {
87 int status;
88
89+ gdb_assert (lp->resumed);
90+
91 status = wait_lwp (lp);
92 if (status == 0)
93 return 0;
f412e1b4 94@@ -2868,110 +2870,61 @@ stop_wait_callback (struct lwp_info *lp,
51a5ef0f
PS
95
96 if (WSTOPSIG (status) != SIGSTOP)
97 {
6ed6bacf 98- if (linux_nat_status_is_event (status))
51a5ef0f
PS
99- {
100- /* If a LWP other than the LWP that we're reporting an
101- event for has hit a GDB breakpoint (as opposed to
102- some random trap signal), then just arrange for it to
103- hit it again later. We don't keep the SIGTRAP status
104- and don't forward the SIGTRAP signal to the LWP. We
105- will handle the current event, eventually we will
106- resume all LWPs, and this one will get its breakpoint
107- trap again.
108-
109- If we do not do this, then we run the risk that the
110- user will delete or disable the breakpoint, but the
111- thread will have already tripped on it. */
112-
113- /* Save the trap's siginfo in case we need it later. */
114- save_siginfo (lp);
115-
116- save_sigtrap (lp);
117-
6ed6bacf 118- /* Now resume this LWP and get the SIGSTOP event. */
51a5ef0f
PS
119- errno = 0;
120- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
121- if (debug_linux_nat)
122- {
123- fprintf_unfiltered (gdb_stdlog,
124- "PTRACE_CONT %s, 0, 0 (%s)\n",
125- target_pid_to_str (lp->ptid),
126- errno ? safe_strerror (errno) : "OK");
127-
128- fprintf_unfiltered (gdb_stdlog,
129- "SWC: Candidate SIGTRAP event in %s\n",
130- target_pid_to_str (lp->ptid));
131- }
132- /* Hold this event/waitstatus while we check to see if
6ed6bacf 133- there are any more (we still want to get that SIGSTOP). */
51a5ef0f
PS
134- stop_wait_callback (lp, NULL);
135+ /* The thread was stopped with a signal other than SIGSTOP. */
136
137- /* Hold the SIGTRAP for handling by linux_nat_wait. If
138- there's another event, throw it back into the
6ed6bacf 139- queue. */
51a5ef0f
PS
140- if (lp->status)
141- {
142- if (debug_linux_nat)
143- fprintf_unfiltered (gdb_stdlog,
144- "SWC: kill %s, %s\n",
145- target_pid_to_str (lp->ptid),
146- status_to_str ((int) status));
147- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
148- }
f412e1b4 149-
6ed6bacf 150- /* Save the sigtrap event. */
51a5ef0f
PS
151- lp->status = status;
152- return 0;
153- }
154- else
155- {
156- /* The thread was stopped with a signal other than
6ed6bacf 157- SIGSTOP, and didn't accidentally trip a breakpoint. */
f412e1b4
PS
158+ /* Save the trap's siginfo in case we need it later. */
159+ save_siginfo (lp);
51a5ef0f
PS
160
161- if (debug_linux_nat)
162- {
163- fprintf_unfiltered (gdb_stdlog,
164- "SWC: Pending event %s in %s\n",
165- status_to_str ((int) status),
166- target_pid_to_str (lp->ptid));
167- }
6ed6bacf 168- /* Now resume this LWP and get the SIGSTOP event. */
51a5ef0f
PS
169- errno = 0;
170- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
171- if (debug_linux_nat)
172- fprintf_unfiltered (gdb_stdlog,
173- "SWC: PTRACE_CONT %s, 0, 0 (%s)\n",
174- target_pid_to_str (lp->ptid),
175- errno ? safe_strerror (errno) : "OK");
f412e1b4
PS
176+ save_sigtrap (lp);
177
51a5ef0f 178- /* Hold this event/waitstatus while we check to see if
6ed6bacf 179- there are any more (we still want to get that SIGSTOP). */
51a5ef0f
PS
180- stop_wait_callback (lp, NULL);
181+ if (debug_linux_nat)
182+ fprintf_unfiltered (gdb_stdlog,
183+ "SWC: Pending event %s in %s\n",
184+ status_to_str ((int) status),
185+ target_pid_to_str (lp->ptid));
186
187- /* If the lp->status field is still empty, use it to
188- hold this event. If not, then this event must be
189- returned to the event queue of the LWP. */
190- if (lp->status)
191- {
192- if (debug_linux_nat)
193- {
194- fprintf_unfiltered (gdb_stdlog,
195- "SWC: kill %s, %s\n",
196- target_pid_to_str (lp->ptid),
197- status_to_str ((int) status));
198- }
199- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (status));
200- }
201- else
202- lp->status = status;
203- return 0;
204- }
6ed6bacf 205+ /* Save the sigtrap event. */
51a5ef0f
PS
206+ lp->status = status;
207+ gdb_assert (! lp->stopped);
208+ gdb_assert (lp->signalled);
209+ lp->stopped = 1;
210 }
211 else
212 {
213 /* We caught the SIGSTOP that we intended to catch, so
214 there's no SIGSTOP pending. */
215- lp->stopped = 1;
216+
217+ if (debug_linux_nat)
218+ fprintf_unfiltered (gdb_stdlog,
219+ "SWC: Delayed SIGSTOP caught for %s.\n",
220+ target_pid_to_str (lp->ptid));
221+
222+ if (lp->step)
223+ {
224+ /* LP->STATUS is 0 here. That means SIGTRAP from
225+ PTRACE_SINGLESTEP still has to be delivered for this inferior
226+ stop. Catching the SIGTRAP event is important to prevent
227+ starvation in select_event_lwp. */
228+
229+ registers_changed ();
230+ linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
231+ 1, TARGET_SIGNAL_0);
232+ if (debug_linux_nat)
233+ fprintf_unfiltered (gdb_stdlog,
234+ "SWC: %s %s, 0, 0 (discard SIGSTOP)\n",
235+ "PTRACE_SINGLESTEP",
236+ target_pid_to_str (lp->ptid));
237+
238+ lp->stopped = 0;
239+ gdb_assert (lp->resumed);
240+ stop_wait_callback (lp, NULL);
241+ gdb_assert (lp->stopped);
242+ }
243+ else
244+ lp->stopped = 1;
245+
246+ /* Reset SIGNALLED only after the stop_wait_callback call above as
247+ it does gdb_assert on SIGNALLED. */
248 lp->signalled = 0;
249 }
250 }
f412e1b4 251@@ -3627,54 +3580,6 @@ retry:
51a5ef0f
PS
252 lp = NULL;
253 }
254
f412e1b4 255- if (lp && lp->signalled && lp->last_resume_kind != resume_stop)
51a5ef0f
PS
256- {
257- /* A pending SIGSTOP may interfere with the normal stream of
258- events. In a typical case where interference is a problem,
259- we have a SIGSTOP signal pending for LWP A while
260- single-stepping it, encounter an event in LWP B, and take the
261- pending SIGSTOP while trying to stop LWP A. After processing
262- the event in LWP B, LWP A is continued, and we'll never see
263- the SIGTRAP associated with the last time we were
264- single-stepping LWP A. */
265-
266- /* Resume the thread. It should halt immediately returning the
267- pending SIGSTOP. */
268- registers_changed ();
f412e1b4
PS
269- if (linux_nat_prepare_to_resume != NULL)
270- linux_nat_prepare_to_resume (lp);
51a5ef0f
PS
271- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
272- lp->step, TARGET_SIGNAL_0);
273- if (debug_linux_nat)
274- fprintf_unfiltered (gdb_stdlog,
275- "LLW: %s %s, 0, 0 (expect SIGSTOP)\n",
276- lp->step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
277- target_pid_to_str (lp->ptid));
278- lp->stopped = 0;
279- gdb_assert (lp->resumed);
280-
281- /* Catch the pending SIGSTOP. */
282- status = lp->status;
283- lp->status = 0;
284-
285- stop_wait_callback (lp, NULL);
286-
287- /* If the lp->status field isn't empty, we caught another signal
288- while flushing the SIGSTOP. Return it back to the event
289- queue of the LWP, as we already have an event to handle. */
290- if (lp->status)
291- {
292- if (debug_linux_nat)
293- fprintf_unfiltered (gdb_stdlog,
294- "LLW: kill %s, %s\n",
295- target_pid_to_str (lp->ptid),
296- status_to_str (lp->status));
297- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
298- }
299-
300- lp->status = status;
301- }
302-
303 if (!target_can_async_p ())
304 {
305 /* Causes SIGINT to be passed on to the attached process. */
f412e1b4 306Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.c
51a5ef0f
PS
307===================================================================
308--- /dev/null 1970-01-01 00:00:00.000000000 +0000
f412e1b4 309+++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.c 2011-12-19 02:16:35.236720272 +0100
51a5ef0f
PS
310@@ -0,0 +1,447 @@
311+/* This testcase is part of GDB, the GNU debugger.
312+
313+ Copyright 2010 Free Software Foundation, Inc.
314+
315+ This program is free software; you can redistribute it and/or modify
316+ it under the terms of the GNU General Public License as published by
317+ the Free Software Foundation; either version 3 of the License, or
318+ (at your option) any later version.
319+
320+ This program is distributed in the hope that it will be useful,
321+ but WITHOUT ANY WARRANTY; without even the implied warranty of
322+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
323+ GNU General Public License for more details.
324+
325+ You should have received a copy of the GNU General Public License
326+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
327+
328+#define _GNU_SOURCE
329+#include <pthread.h>
330+#include <stdio.h>
331+#include <limits.h>
332+#include <errno.h>
333+#include <stdlib.h>
334+#include <string.h>
335+#include <assert.h>
336+#include <sys/types.h>
337+#include <signal.h>
338+#include <unistd.h>
339+#include <asm/unistd.h>
340+
341+#define gettid() syscall (__NR_gettid)
342+#define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig)
343+
344+/* Terminate always in the main task, it can lock up with SIGSTOPped GDB
345+ otherwise. */
346+#define TIMEOUT (gettid () == getpid() ? 10 : 15)
347+
348+static pid_t thread1_tid;
349+static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER;
350+static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
351+static int thread1_sigusr1_hit;
352+static int thread1_sigusr2_hit;
353+
354+static pid_t thread2_tid;
355+static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER;
356+static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
357+static int thread2_sigusr1_hit;
358+static int thread2_sigusr2_hit;
359+
360+static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
361+
362+/* Do not use alarm as it would create a ptrace event which would hang up us if
363+ we are being traced by GDB which we stopped ourselves. */
364+
365+static void timed_mutex_lock (pthread_mutex_t *mutex)
366+{
367+ int i;
368+ struct timespec start, now;
369+
370+ i = clock_gettime (CLOCK_MONOTONIC, &start);
371+ assert (i == 0);
372+
373+ do
374+ {
375+ i = pthread_mutex_trylock (mutex);
376+ if (i == 0)
377+ return;
378+ assert (i == EBUSY);
379+
380+ i = clock_gettime (CLOCK_MONOTONIC, &now);
381+ assert (i == 0);
382+ assert (now.tv_sec >= start.tv_sec);
383+ }
384+ while (now.tv_sec - start.tv_sec < TIMEOUT);
385+
386+ fprintf (stderr, "Timed out waiting for internal lock!\n");
387+ exit (EXIT_FAILURE);
388+}
389+
390+static void
391+handler (int signo, siginfo_t *siginfo, void *exception)
392+{
393+ int *varp;
394+
395+ assert (siginfo->si_signo == signo);
396+ assert (siginfo->si_code == SI_TKILL);
397+ assert (siginfo->si_pid == getpid ());
398+
399+ if (gettid () == thread1_tid)
400+ {
401+ if (signo == SIGUSR1)
402+ varp = &thread1_sigusr1_hit;
403+ else if (signo == SIGUSR2)
404+ varp = &thread1_sigusr2_hit;
405+ else
406+ assert (0);
407+ }
408+ else if (gettid () == thread2_tid)
409+ {
410+ if (signo == SIGUSR1)
411+ varp = &thread2_sigusr1_hit;
412+ else if (signo == SIGUSR2)
413+ varp = &thread2_sigusr2_hit;
414+ else
415+ assert (0);
416+ }
417+ else
418+ assert (0);
419+
420+ if (*varp)
421+ {
422+ fprintf (stderr, "Signal %d for TID %lu has been already hit!\n", signo,
423+ (unsigned long) gettid ());
424+ exit (EXIT_FAILURE);
425+ }
426+ *varp = 1;
427+}
428+
429+static void *
430+thread1_func (void *unused)
431+{
432+ int i;
433+
434+ timed_mutex_lock (&thread1_tid_mutex);
435+
436+ /* THREAD1_TID_MUTEX must be already locked to avoid race. */
437+ thread1_tid = gettid ();
438+
439+ i = pthread_cond_signal (&thread1_tid_cond);
440+ assert (i == 0);
441+ i = pthread_mutex_unlock (&thread1_tid_mutex);
442+ assert (i == 0);
443+
444+ /* Be sure the "t (tracing stop)" test can proceed for both threads. */
445+ timed_mutex_lock (&terminate_mutex);
446+ i = pthread_mutex_unlock (&terminate_mutex);
447+ assert (i == 0);
448+
449+ if (! thread1_sigusr1_hit)
450+ {
451+ fprintf (stderr, "Thread 1 signal SIGUSR1 not hit!\n");
452+ exit (EXIT_FAILURE);
453+ }
454+ if (! thread1_sigusr2_hit)
455+ {
456+ fprintf (stderr, "Thread 1 signal SIGUSR2 not hit!\n");
457+ exit (EXIT_FAILURE);
458+ }
459+
460+ return NULL;
461+}
462+
463+static void *
464+thread2_func (void *unused)
465+{
466+ int i;
467+
468+ timed_mutex_lock (&thread2_tid_mutex);
469+
470+ /* THREAD2_TID_MUTEX must be already locked to avoid race. */
471+ thread2_tid = gettid ();
472+
473+ i = pthread_cond_signal (&thread2_tid_cond);
474+ assert (i == 0);
475+ i = pthread_mutex_unlock (&thread2_tid_mutex);
476+ assert (i == 0);
477+
478+ /* Be sure the "t (tracing stop)" test can proceed for both threads. */
479+ timed_mutex_lock (&terminate_mutex);
480+ i = pthread_mutex_unlock (&terminate_mutex);
481+ assert (i == 0);
482+
483+ if (! thread2_sigusr1_hit)
484+ {
485+ fprintf (stderr, "Thread 2 signal SIGUSR1 not hit!\n");
486+ exit (EXIT_FAILURE);
487+ }
488+ if (! thread2_sigusr2_hit)
489+ {
490+ fprintf (stderr, "Thread 2 signal SIGUSR2 not hit!\n");
491+ exit (EXIT_FAILURE);
492+ }
493+
494+ return NULL;
495+}
496+
497+static const char *
498+proc_string (const char *filename, const char *line)
499+{
500+ FILE *f;
501+ static char buf[LINE_MAX];
502+ size_t line_len = strlen (line);
503+
504+ f = fopen (filename, "r");
505+ if (f == NULL)
506+ {
507+ fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line,
508+ strerror (errno));
509+ exit (EXIT_FAILURE);
510+ }
511+ while (errno = 0, fgets (buf, sizeof (buf), f))
512+ {
513+ char *s;
514+
515+ s = strchr (buf, '\n');
516+ assert (s != NULL);
517+ *s = 0;
518+
519+ if (strncmp (buf, line, line_len) != 0)
520+ continue;
521+
522+ if (fclose (f))
523+ {
524+ fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line,
525+ strerror (errno));
526+ exit (EXIT_FAILURE);
527+ }
528+
529+ return &buf[line_len];
530+ }
531+ if (errno != 0)
532+ {
533+ fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno));
534+ exit (EXIT_FAILURE);
535+ }
536+ fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line);
537+ exit (EXIT_FAILURE);
538+}
539+
540+static unsigned long
541+proc_ulong (const char *filename, const char *line)
542+{
543+ const char *s = proc_string (filename, line);
544+ long retval;
545+ char *end;
546+
547+ errno = 0;
548+ retval = strtol (s, &end, 10);
549+ if (retval < 0 || retval >= LONG_MAX || (end && *end))
550+ {
551+ fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval,
552+ strerror (errno));
553+ exit (EXIT_FAILURE);
554+ }
555+ return retval;
556+}
557+
558+static void
559+state_wait (pid_t process, const char *wanted)
560+{
561+ char *filename;
562+ int i;
563+ struct timespec start, now;
564+ const char *state;
565+
566+ i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process);
567+ assert (i > 0);
568+
569+ i = clock_gettime (CLOCK_MONOTONIC, &start);
570+ assert (i == 0);
571+
572+ do
573+ {
574+ state = proc_string (filename, "State:\t");
575+
576+ /* torvalds/linux-2.6.git 464763cf1c6df632dccc8f2f4c7e50163154a2c0
577+ has changed "T (tracing stop)" to "t (tracing stop)". Make the GDB
578+ testcase backward compatible with older Linux kernels. */
579+ if (strcmp (state, "T (tracing stop)") == 0)
580+ state = "t (tracing stop)";
581+
582+ if (strcmp (state, wanted) == 0)
583+ {
584+ free (filename);
585+ return;
586+ }
587+
588+ if (sched_yield ())
589+ {
590+ perror ("sched_yield()");
591+ exit (EXIT_FAILURE);
592+ }
593+
594+ i = clock_gettime (CLOCK_MONOTONIC, &now);
595+ assert (i == 0);
596+ assert (now.tv_sec >= start.tv_sec);
597+ }
598+ while (now.tv_sec - start.tv_sec < TIMEOUT);
599+
600+ fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
601+ (unsigned long) process, wanted, state);
602+ exit (EXIT_FAILURE);
603+}
604+
605+static volatile pid_t tracer = 0;
606+static pthread_t thread1, thread2;
607+
608+static void
609+cleanup (void)
610+{
611+ printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer);
612+
613+ if (tracer)
614+ {
615+ int i;
616+ int tracer_save = tracer;
617+
618+ tracer = 0;
619+
620+ i = kill (tracer_save, SIGCONT);
621+ assert (i == 0);
622+ }
623+}
624+
625+int
626+main (int argc, char **argv)
627+{
628+ int i;
629+ int standalone = 0;
630+ struct sigaction act;
631+
632+ if (argc == 2 && strcmp (argv[1], "-s") == 0)
633+ standalone = 1;
634+ else
635+ assert (argc == 1);
636+
637+ setbuf (stdout, NULL);
638+
639+ timed_mutex_lock (&thread1_tid_mutex);
640+ timed_mutex_lock (&thread2_tid_mutex);
641+
642+ timed_mutex_lock (&terminate_mutex);
643+
644+ errno = 0;
645+ memset (&act, 0, sizeof (act));
646+ act.sa_sigaction = handler;
647+ act.sa_flags = SA_RESTART | SA_SIGINFO;
648+ i = sigemptyset (&act.sa_mask);
649+ assert_perror (errno);
650+ assert (i == 0);
651+ i = sigaction (SIGUSR1, &act, NULL);
652+ assert_perror (errno);
653+ assert (i == 0);
654+ i = sigaction (SIGUSR2, &act, NULL);
655+ assert_perror (errno);
656+ assert (i == 0);
657+
658+ i = pthread_create (&thread1, NULL, thread1_func, NULL);
659+ assert (i == 0);
660+
661+ i = pthread_create (&thread2, NULL, thread2_func, NULL);
662+ assert (i == 0);
663+
664+ if (!standalone)
665+ {
666+ tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
667+ if (tracer == 0)
668+ {
669+ fprintf (stderr, "The testcase must be run by GDB!\n");
670+ exit (EXIT_FAILURE);
671+ }
672+ if (tracer != getppid ())
673+ {
674+ fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
675+ exit (EXIT_FAILURE);
676+ }
677+ }
678+
679+ /* SIGCONT our debugger in the case of our crash as we would deadlock
680+ otherwise. */
681+
682+ atexit (cleanup);
683+
684+ printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);
685+
686+ if (tracer)
687+ {
688+ i = kill (tracer, SIGSTOP);
689+ assert (i == 0);
690+ state_wait (tracer, "T (stopped)");
691+ }
692+
693+ /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so
694+ they could not trigger the signals before GDB gets unstopped later.
695+ Threads get resumed at pthread_cond_wait below. Use `while' loops for
696+ protection against spurious pthread_cond_wait wakeups. */
697+
698+ printf ("Waiting till the threads initialize their TIDs.\n");
699+
700+ while (thread1_tid == 0)
701+ {
702+ i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
703+ assert (i == 0);
704+ }
705+
706+ while (thread2_tid == 0)
707+ {
708+ i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
709+ assert (i == 0);
710+ }
711+
712+ printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
713+ (unsigned long) thread1_tid, (unsigned long) thread2_tid,
714+ (unsigned long) getpid ());
715+
716+ errno = 0;
717+ i = tgkill (getpid (), thread1_tid, SIGUSR1);
718+ assert_perror (errno);
719+ assert (i == 0);
720+ i = tgkill (getpid (), thread1_tid, SIGUSR2);
721+ assert_perror (errno);
722+ assert (i == 0);
723+ i = tgkill (getpid (), thread2_tid, SIGUSR1);
724+ assert_perror (errno);
725+ assert (i == 0);
726+ i = tgkill (getpid (), thread2_tid, SIGUSR2);
727+ assert_perror (errno);
728+ assert (i == 0);
729+
730+ printf ("Waiting till the threads get trapped by the signals.\n");
731+
732+ if (tracer)
733+ {
734+ /* s390x-unknown-linux-gnu will fail with "R (running)". */
735+
736+ state_wait (thread1_tid, "t (tracing stop)");
737+
738+ state_wait (thread2_tid, "t (tracing stop)");
739+ }
740+
741+ cleanup ();
742+
743+ printf ("Joining the threads.\n");
744+
745+ i = pthread_mutex_unlock (&terminate_mutex);
746+ assert (i == 0);
747+
748+ i = pthread_join (thread1, NULL);
749+ assert (i == 0);
750+
751+ i = pthread_join (thread2, NULL);
752+ assert (i == 0);
753+
754+ printf ("Exiting.\n"); /* break-at-exit */
755+
756+ return EXIT_SUCCESS;
757+}
f412e1b4 758Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.exp
51a5ef0f
PS
759===================================================================
760--- /dev/null 1970-01-01 00:00:00.000000000 +0000
f412e1b4 761+++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.exp 2011-12-19 02:16:35.237720268 +0100
51a5ef0f
PS
762@@ -0,0 +1,94 @@
763+# Copyright 2010 Free Software Foundation, Inc.
764+
765+# This program is free software; you can redistribute it and/or modify
766+# it under the terms of the GNU General Public License as published by
767+# the Free Software Foundation; either version 3 of the License, or
768+# (at your option) any later version.
769+#
770+# This program is distributed in the hope that it will be useful,
771+# but WITHOUT ANY WARRANTY; without even the implied warranty of
772+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
773+# GNU General Public License for more details.
774+#
775+# You should have received a copy of the GNU General Public License
776+# along with this program. If not, see <http://www.gnu.org/licenses/>.
777+
778+set testfile "siginfo-threads"
779+set srcfile ${testfile}.c
780+set binfile ${objdir}/${subdir}/${testfile}
781+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" ${binfile} executable [list debug additional_flags=-lrt]] != "" } {
782+ return -1
783+}
784+
785+clean_restart $testfile
786+
787+if ![runto_main] {
788+ return -1
789+}
790+
791+# `nostop noprint pass' could in some cases report false PASS due to the
792+# (preempt 'handle') code path.
793+
794+gdb_test "handle SIGUSR1 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR1\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\].*"
795+gdb_test "handle SIGUSR2 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR2\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\].*"
796+
797+gdb_breakpoint [gdb_get_line_number "break-at-exit"]
798+
799+set test "get pid"
800+gdb_test_multiple "p getpid ()" $test {
801+ -re " = (\[0-9\]+)\r\n$gdb_prompt $" {
802+ set pid $expect_out(1,string)
803+ pass $test
804+ }
805+}
806+
807+for {set sigcount 0} {$sigcount < 4} {incr sigcount} {
808+ set test "catch signal $sigcount"
809+ set sigusr ""
810+ gdb_test_multiple "continue" $test {
811+ -re "Program received signal SIGUSR(\[12\]), User defined signal \[12\]\\.\r\n.*\r\n$gdb_prompt $" {
812+ set sigusr $expect_out(1,string)
813+ pass $test
814+ }
815+ }
816+ if {$sigusr == ""} {
817+ return -1
818+ }
819+
820+ set test "signal $sigcount si_signo"
821+ if {$sigusr == 1} {
822+ set signo 10
823+ } else {
824+ set signo 12
825+ }
826+ gdb_test_multiple {p $_siginfo.si_signo} $test {
827+ -re " = $signo\r\n$gdb_prompt $" {
828+ pass $test
829+ }
830+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
831+ unsupported $test
832+ }
833+ }
834+
835+ set test "signal $sigcount si_code is SI_TKILL"
836+ gdb_test_multiple {p $_siginfo.si_code} $test {
837+ -re " = -6\r\n$gdb_prompt $" {
838+ pass $test
839+ }
840+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
841+ unsupported $test
842+ }
843+ }
844+
845+ set test "signal $sigcount si_pid"
846+ gdb_test_multiple {p $_siginfo._sifields._kill.si_pid} $test {
847+ -re " = $pid\r\n$gdb_prompt $" {
848+ pass $test
849+ }
850+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
851+ unsupported $test
852+ }
853+ }
854+}
855+
856+gdb_continue_to_breakpoint break-at-exit ".*break-at-exit.*"
f412e1b4 857Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.c
51a5ef0f
PS
858===================================================================
859--- /dev/null 1970-01-01 00:00:00.000000000 +0000
f412e1b4 860+++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.c 2011-12-19 02:16:35.237720268 +0100
51a5ef0f
PS
861@@ -0,0 +1,54 @@
862+/* This testcase is part of GDB, the GNU debugger.
863+
864+ Copyright 2010 Free Software Foundation, Inc.
865+
866+ This program is free software; you can redistribute it and/or modify
867+ it under the terms of the GNU General Public License as published by
868+ the Free Software Foundation; either version 3 of the License, or
869+ (at your option) any later version.
870+
871+ This program is distributed in the hope that it will be useful,
872+ but WITHOUT ANY WARRANTY; without even the implied warranty of
873+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
874+ GNU General Public License for more details.
875+
876+ You should have received a copy of the GNU General Public License
877+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
878+
879+#include <pthread.h>
880+#include <assert.h>
881+#include <signal.h>
882+
883+#include <asm/unistd.h>
884+#include <unistd.h>
885+#define tgkill(tgid, tid, sig) syscall (__NR_tgkill, (tgid), (tid), (sig))
886+#define gettid() syscall (__NR_gettid)
887+
888+static volatile int var;
889+
890+static void
891+handler (int signo) /* step-0 */
892+{ /* step-0 */
893+ var++; /* step-1 */
894+ tgkill (getpid (), gettid (), SIGUSR1); /* step-2 */
895+}
896+
897+static void *
898+start (void *arg)
899+{
900+ signal (SIGUSR1, handler);
901+ tgkill (getpid (), gettid (), SIGUSR1);
902+ assert (0);
903+
904+ return NULL;
905+}
906+
907+int
908+main (void)
909+{
910+ pthread_t thread;
911+
912+ pthread_create (&thread, NULL, start, NULL);
913+ start (NULL); /* main-start */
914+ return 0;
915+}
f412e1b4 916Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.exp
51a5ef0f
PS
917===================================================================
918--- /dev/null 1970-01-01 00:00:00.000000000 +0000
f412e1b4 919+++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.exp 2011-12-19 02:16:35.237720268 +0100
51a5ef0f
PS
920@@ -0,0 +1,74 @@
921+# Copyright 2010 Free Software Foundation, Inc.
922+
923+# This program is free software; you can redistribute it and/or modify
924+# it under the terms of the GNU General Public License as published by
925+# the Free Software Foundation; either version 3 of the License, or
926+# (at your option) any later version.
927+#
928+# This program is distributed in the hope that it will be useful,
929+# but WITHOUT ANY WARRANTY; without even the implied warranty of
930+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
931+# GNU General Public License for more details.
932+#
933+# You should have received a copy of the GNU General Public License
934+# along with this program. If not, see <http://www.gnu.org/licenses/>.
935+
936+set testfile sigstep-threads
937+set srcfile ${testfile}.c
938+set executable ${testfile}
939+set binfile ${objdir}/${subdir}/${executable}
940+
941+if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
942+ untested ${testfile}.exp
943+ return -1
944+}
945+
946+clean_restart $executable
947+
948+if ![runto_main] {
949+ return -1;
950+}
951+
952+# `noprint' would not test the full logic of GDB.
953+gdb_test "handle SIGUSR1 nostop print pass" "\r\nSIGUSR1\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\].*"
954+
955+gdb_test_no_output "set scheduler-locking off"
956+
957+gdb_breakpoint [gdb_get_line_number "step-1"]
958+gdb_test_no_output {set $step1=$bpnum}
959+gdb_continue_to_breakpoint "step-1" ".* step-1 .*"
960+gdb_test_no_output {disable $step1}
961+
962+# 1 as we are now stopped at the `step-1' label.
963+set step_at 1
964+for {set i 0} {$i < 100} {incr i} {
965+ set test "step $i"
966+ # Presume this step failed - as in the case of a timeout.
967+ set failed 1
968+ gdb_test_multiple "step" $test {
969+ -re "\r\nProgram received signal SIGUSR1, User defined signal 1.\r\n" {
970+ exp_continue -continue_timer
971+ }
972+ -re "step-(\[012\]).*\r\n$gdb_prompt $" {
973+ set now $expect_out(1,string)
974+ if {$step_at == 2 && $now == 1} {
975+ set failed 0
976+ } elseif {$step_at == 1 && $now == 2} {
977+ set failed 0
978+ # Continue over the re-signalling back to the handle entry.
979+ gdb_test_no_output {enable $step1} ""
980+ gdb_test "continue" " step-1 .*" ""
981+ set now 1
982+ gdb_test_no_output {disable $step1} ""
983+ } else {
984+ fail $test
985+ }
986+ set step_at $now
987+ }
988+ }
989+ if $failed {
990+ return
991+ }
992+}
993+# We can never reliably say the racy problematic case has been tested.
994+pass "step"
This page took 0.242438 seconds and 4 git commands to generate.