]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-bz592031-siginfo-lost-4of5.patch
- updated (performance fixes).
[packages/gdb.git] / gdb-bz592031-siginfo-lost-4of5.patch
1 http://sourceware.org/ml/gdb-patches/2010-09/msg00360.html
2 Subject: [patch 3/4]#3 linux-nat: Do not respawn signals
3
4 Hi,
5
6 linux-nat.c is fixed to never respawn signals; possibly keeping SIGSTOP
7 pending, 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
10 The last linux-nat.c removed patch chunk comes from the initial implementation
11 by Mark Kettenis:
12         [PATCH] New Linux threads support
13         http://sourceware.org/ml/gdb-patches/2000-09/msg00020.html
14         92280a75e017683bf8e4f339f4f85640b0700509
15 It gets in part reimplemented into the new stop_wait_callback <if (lp->step)>
16 part and partially just not needed as currently GDB never drops the signals as
17 it does not PTRACE_CONT the thread; signal is kept for processing:
18         "RC: Not resuming sibling %s (has pending)\n"
19
20 In stop_wait_callback I believe breakpoints cancellation is not needed here,
21 it would be done later.
22
23
24 The testcase sigstep-threads.exp was written to catch a regression-like
25 appearance then the new <if (lp->step)> part of stop_wait_callback gets
26 removed.  Still the tecase fails even with FSF HEAD:
27
28 32        var++;                /* step-1 */
29 (gdb) step
30 Program received signal SIGUSR1, User defined signal 1.
31 Program received signal SIGUSR1, User defined signal 1.
32 31      {                       /* step-0 */
33
34 There is no reason why it shouldn't stop on line 33, between line 32 and line
35 33 no signal would occur.  Stepping of the current thread should not be
36 affected by whatever happens in the other threads as select_event_lwp has:
37   /* Give preference to any LWP that is being single-stepped.  */
38
39 There is a problem that with FSF HEAD GDB does PTRACE_SINGLESTEP for thread A,
40 PTRACE_CONT for thread B (because of set scheduler-locking off), thread B hits
41 SIGUSR1, so GDB tkills thread A with SIGSTOP and it can receive SIGSTOP for
42 thread A before the SIGTRAP for completed PTRACE_SINGLESTEP.  At that moment
43 select_event_lwp. forgets it was stepping thread A because there is no pending
44 SIGTRAP event.  currently_stepping still remembers thread A was stepping so it
45 will later stop but as thread A was PTRACE_CONT-ed in the meantime it is too
46 late.
47
48 There is the new <if (lp->step)> part of stop_wait_callback to always track
49 thread A is stepping.  Due to different scheduling without this part the
50 changed GDB would very rarely stop in this testcase otherwise, making it look
51 as a regression.
52
53 I have some another patch I may post separately as if multiple signals happen
54 besides SIGTRAP GDB still may switch from thread A away (as not considering it
55 stepping) to thread B for SIGUSR and accidentally PTRACE_CONT thread A.
56 But I do not find this as a prerequisite for this patchset.
57
58
59
60 Thanks,
61 Jan
62
63
64 gdb/
65 2010-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
73 gdb/testsuite/
74 2010-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
81 Index: gdb-7.4.50.20111218/gdb/linux-nat.c
82 ===================================================================
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,
86      {
87        int status;
88  
89 +      gdb_assert (lp->resumed);
90 +
91        status = wait_lwp (lp);
92        if (status == 0)
93         return 0;
94 @@ -2868,110 +2870,61 @@ stop_wait_callback (struct lwp_info *lp,
95  
96        if (WSTOPSIG (status) != SIGSTOP)
97         {
98 -         if (linux_nat_status_is_event (status))
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 -
118 -             /* Now resume this LWP and get the SIGSTOP event.  */
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
133 -                there are any more (we still want to get that SIGSTOP).  */
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
139 -                queue.  */
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 -               }
149 -
150 -             /* Save the sigtrap event.  */
151 -             lp->status = status;
152 -             return 0;
153 -           }
154 -         else
155 -           {
156 -             /* The thread was stopped with a signal other than
157 -                SIGSTOP, and didn't accidentally trip a breakpoint.  */
158 +         /* Save the trap's siginfo in case we need it later.  */
159 +         save_siginfo (lp);
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 -               }
168 -             /* Now resume this LWP and get the SIGSTOP event.  */
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");
176 +         save_sigtrap (lp);
177  
178 -             /* Hold this event/waitstatus while we check to see if
179 -                there are any more (we still want to get that SIGSTOP).  */
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 -           }
205 +         /* Save the sigtrap event.  */
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      }
251 @@ -3627,54 +3580,6 @@ retry:
252         lp = NULL;
253      }
254  
255 -  if (lp && lp->signalled && lp->last_resume_kind != resume_stop)
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 ();
269 -      if (linux_nat_prepare_to_resume != NULL)
270 -       linux_nat_prepare_to_resume (lp);
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.  */
306 Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.c
307 ===================================================================
308 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
309 +++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.c     2011-12-19 02:16:35.236720272 +0100
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 +}
758 Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.exp
759 ===================================================================
760 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
761 +++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/siginfo-threads.exp   2011-12-19 02:16:35.237720268 +0100
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.*"
857 Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.c
858 ===================================================================
859 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
860 +++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.c     2011-12-19 02:16:35.237720268 +0100
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 +}
916 Index: gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.exp
917 ===================================================================
918 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
919 +++ gdb-7.4.50.20111218/gdb/testsuite/gdb.threads/sigstep-threads.exp   2011-12-19 02:16:35.237720268 +0100
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.168738 seconds and 3 git commands to generate.