Handle less threads caught during the inferior's initialization.
[debugger.git] / testsuite.c
1 /* Copyright 2007, Red Hat Inc.  */
2
3 #define _GNU_SOURCE 1
4
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <assert.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <unistd.h>
11 #include <limits.h>
12 #include <string.h>
13 #include <pthread.h>
14 #include <sys/syscall.h>
15 #include <dlfcn.h>
16
17 #include "debugger.h"
18
19 #define LIBRARY 1
20 #include "debugger.c"
21
22
23 #define TIMEOUT_SECS 4
24 #undef LOOPS_MIN
25 #define LOOPS_MIN 1000
26
27
28 #define tkill(tid, sig) syscall (SYS_tkill, (tid), (sig))
29
30
31 static volatile int spawned_threads_count;      /* Set for the specific spawner.  */
32
33 static struct attach_state_struct *attach_checked (pid_t pid, int redelivered_expect)
34 {
35   struct attach_state_struct *attach_state;
36   time_t timeout = time (NULL) + TIMEOUT_SECS;
37   unsigned loops = 0;
38
39   STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING) | (1 << STATE_STOPPED));
40   do
41     {
42       attach_state = attach (pid);
43       if (redelivered_expect != attach_state_redelivered_get (attach_state))
44         {
45           fprintf (stderr, "Expecting redelivery of %d but found %d\n",
46                    redelivered_expect,
47                    attach_state_redelivered_get (attach_state));
48           abort ();
49         }
50       if (attach_state_threads_count_get (attach_state)
51           == spawned_threads_count)
52         break;
53       /* During the inferior's initialization we may catch less threads.  */
54       assert (attach_state_threads_count_get (attach_state)
55               < spawned_threads_count);
56       /* WARNING: Currently we never use REDELIVERED_EXPECT but we would have to
57          probably reset it back to 0 otherwise.  */
58       assert (redelivered_expect == 0);
59     }
60   while (loops++ < LOOPS_MIN || time (NULL) < timeout);
61
62   /* FIXME: Why also STATE_STOPPED?  */
63   STATE (pid, (1 << STATE_PTRACED) | (1 << STATE_STOPPED));
64   return attach_state;
65 }
66
67 static void detach_checked (struct attach_state_struct *attach_state)
68 {
69   pid_t pid = attach_state_pid_get (attach_state);
70
71   if (attach_state_stopped_get (attach_state) != 0)
72     {
73       STATE (pid, 1 << STATE_STOPPED);
74       detach (attach_state);
75       STATE (pid, 1 << STATE_STOPPED);
76     }
77   else
78     {
79       STATE (pid, (1 << STATE_PTRACED));
80       detach (attach_state);
81       STATE (pid, ((1 << STATE_SLEEPING) | (1 << STATE_RUNNING)));
82     }
83 }
84
85 struct registry
86   {
87     struct registry *next;
88     pid_t pid;
89   };
90 struct registry *registry_list;
91
92 static void registry_add (pid_t pid)
93 {
94   struct registry *new;
95
96   new = malloc (sizeof (*new));
97   assert (new != NULL);
98   new->pid = pid;
99   new->next = registry_list;
100   registry_list = new;
101 }
102
103 static void registry_remove (pid_t pid)
104 {
105   struct registry **iter_pointer;
106
107   for (iter_pointer = &registry_list; *iter_pointer != NULL;
108        iter_pointer = &(*iter_pointer)->next)
109     {
110       struct registry *found = *iter_pointer;
111       if (found->pid != pid)
112         continue;
113
114       *iter_pointer = found->next;
115       free (found);
116       return;
117     }
118   abort ();
119 }
120
121 static void registry_atexit (void)
122 {
123   struct registry *iter;
124
125   for (iter = registry_list; iter != NULL; iter = iter->next)
126     {
127       tkill (iter->pid, SIGCONT);
128       tkill (iter->pid, SIGKILL);
129       kill (iter->pid, SIGKILL);
130     }
131 }
132
133 static void registry_cleanup (void)
134 {
135   struct registry *iter;
136   pid_t pid;
137
138   registry_atexit ();
139   while ((pid = wait (NULL)) != -1)
140     {
141       for (iter = registry_list; iter != NULL; iter = iter->next)
142         if (iter->pid == pid)
143           break;
144       assert (iter != NULL);
145     }
146   assert (errno == ECHILD);
147   while (registry_list)
148     {
149       iter = registry_list;
150       registry_list = iter->next;
151       free (iter);
152     }
153 }
154
155 static void registry_handler (int signo)
156 {
157   signal (signo, SIG_DFL);
158   registry_atexit ();
159   raise (signo);
160 }
161
162 static __attribute__((__noreturn__)) void child_pause (void)
163 {
164   for (;;)
165     pause ();
166   /* NOTREACHED */
167   abort ();
168 }
169
170 static void child_alrm_handler (int signo)
171 {
172   assert (signo == SIGALRM);
173   raise (SIGALRM);
174 }
175
176 static __attribute__((__noreturn__)) void child_alrm (void)
177 {
178   void (*handler_orig) (int signo);
179 #if 0
180   int i;
181   sigset_t oldset;
182 #endif
183
184   handler_orig = signal (SIGALRM, child_alrm_handler);
185   assert (handler_orig == SIG_DFL);
186
187 #if 0
188   i = sigprocmask (SIG_BLOCK, NULL, &oldset);
189   assert (i == 0);
190   printf ("sigprocmask () -> sigismember (SIGALRM) == %d\n", sigismember (&oldset, SIGALRM));
191 #endif
192
193   for (;;)
194     pause ();
195   /* NOTREACHED */
196   abort ();
197 }
198
199 static pid_t spawn (void *(*child) (void *data, void *input), void *data,
200                     void *input, int fd_close)
201 {
202   pid_t pid;
203
204   pid = fork();
205   switch (pid)
206     {
207       case -1:
208         perror ("fork()");
209         exit (EXIT_FAILURE);
210         /* NOTREACHED */
211       case 0:
212         if (fd_close != -1)
213           {
214             int i;
215
216             i = close (fd_close);
217             assert (i == 0);
218           }
219         child (data, input);
220         /* NOTREACHED */
221         abort ();
222       default:;
223         /* PASSTHRU */
224     }
225   /* Parent.  */
226
227   registry_add (pid);
228   STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING));
229   return pid;
230 }
231
232 static void murder (pid_t pid)
233 {
234   int i;
235   pid_t pid_got;
236   int status;
237
238   if (pid == 0)
239     return;
240
241   i = kill (pid, SIGKILL);
242   assert (i == 0);
243
244   pid_got = waitpid (pid, &status, 0);
245   if (!(pid_got == -1 && errno == ECHILD))
246     {
247       assert (pid_got == pid);
248       assert ((WIFSIGNALED (status) && (WTERMSIG (status) == SIGKILL
249                                         || WTERMSIG (status) == SIGUSR2))
250               || (WIFEXITED (status) && WEXITSTATUS (status) == 0));
251       STATE (pid, 1 << STATE_ENOENT);
252     }
253   else
254     STATE (pid, (1 << STATE_ENOENT) | (1 << STATE_ZOMBIE));
255
256   registry_remove (pid);
257 }
258
259
260 struct child_spawner
261   {
262     void *(*child) (void *data, void *input);
263     void *data;
264     int fd;
265   };
266
267 static __attribute__((__noreturn__)) void *child_spawner (void *param_voidpointer, void *input)
268 {
269   struct child_spawner *param = param_voidpointer;
270   pid_t inferior;
271   ssize_t inferior_size;
272   int i;
273
274   inferior = spawn (param->child, param->data, input, param->fd);
275
276   inferior_size = write (param->fd, &inferior, sizeof (inferior));
277   assert (inferior_size == sizeof (inferior));
278   i = close (param->fd);
279   assert (i == 0);
280
281   waitpid (inferior, NULL, 0);
282   _exit (EXIT_SUCCESS);
283   /* NOTREACHED */
284   abort ();
285 }
286
287 struct spawner
288   {
289     void *(*func) (void *data, void *input);
290     void *data;
291   };
292
293 static void *spawn_with_waiter (void *data, void *input)
294 {
295   pid_t waiter;
296   struct child_spawner param_local;
297   int pipefds[2];
298   int i;
299   pid_t inferior;
300   ssize_t inferior_size;
301   unsigned char buf;
302   ssize_t buf_size;
303   struct spawner *param = data;
304
305   assert (data != NULL);
306
307   i = pipe (pipefds);
308   assert (i == 0);
309
310   param_local.child = param->func;
311   param_local.data = param->data;
312   param_local.fd = pipefds[1];
313   waiter = spawn (child_spawner, &param_local, input, pipefds[0]);
314
315   i = close (pipefds[1]);
316   assert (i == 0);
317   inferior_size = read (pipefds[0], &inferior, sizeof (inferior));
318   assert (inferior_size == sizeof (inferior));
319   buf_size = read (pipefds[0], &buf, sizeof (buf));
320   assert (buf_size == 0);
321   i = close (pipefds[0]);
322   assert (i == 0);
323
324   registry_add (inferior);
325
326   return (void *) (unsigned long) inferior;
327 }
328
329 static void *spawn_without_waiter (void *data, void *input)
330 {
331   struct spawner *param = data;
332
333   return (void *) (unsigned long) spawn (param->func, param->data, input, -1);
334 }
335
336 static void body_spawner (void *(*child) (void *data, void *input), void *data,
337                           void *input)
338 {
339   pid_t inferior;
340   struct attach_state_struct *attach_state;
341   int i;
342
343   assert (input == NULL);
344
345   /* Plain attach/detach.  */
346   inferior = (unsigned long) (*child) (data, child_pause);
347   attach_state = attach_checked (inferior, 0);
348   assert (attach_state_stopped_get (attach_state) == 0);
349   detach_checked (attach_state);
350   murder (inferior);
351
352   /* Attach to a process stopped by standard kill(2).  */
353   inferior = (unsigned long) (*child) (data, child_pause);
354   delay ();
355   i = kill (inferior, SIGSTOP);
356   assert (i == 0);
357   STATE (inferior, 1 << STATE_STOPPED);
358   attach_state = attach_checked (inferior, 0);
359   assert (attach_state_stopped_get (attach_state) == 1);
360   detach_checked (attach_state);
361   murder (inferior);
362
363   /* Attach to a process stopped by Linux specific tkill(2).  */
364   inferior = (unsigned long) (*child) (data, child_pause);
365   delay ();
366   i = tkill (inferior, SIGSTOP);
367   assert (i == 0);
368   STATE (inferior, 1 << STATE_STOPPED);
369   attach_state = attach_checked (inferior, 0);
370   assert (attach_state_stopped_get (attach_state) == 1);
371   detach_checked (attach_state);
372   murder (inferior);
373
374   /* Attach to a stopped process with already pending SIGALRM.  */
375   inferior = (unsigned long) (*child) (data, child_alrm);
376   STATE (inferior, 1 << STATE_SLEEPING);
377   delay ();
378   i = tkill (inferior, SIGSTOP);
379   assert (i == 0);
380   /* Wait till it gets stopped otherwise we may get STATE_ENOENT below.  */
381   STATE (inferior, 1 << STATE_STOPPED);
382   delay ();
383   i = tkill (inferior, SIGALRM);
384   assert (i == 0);
385   STATE (inferior, 1 << STATE_STOPPED);
386   /* FIXME: SIGALRM did not get redelivered?  */
387 #if 0
388   attach_state = attach_checked (inferior, SIGALRM);
389 #else
390   attach_state = attach_checked (inferior, 0);
391 #endif
392   assert (attach_state_stopped_get (attach_state) == 1);
393   detach_checked (attach_state);
394   STATE (inferior, 1 << STATE_STOPPED);
395   delay ();
396   i = tkill (inferior, SIGCONT);
397   assert (i == 0);
398   /* This is a race, we may not prove the successful SIGALRM delivery by it.
399      Rather recheck it below.  */
400   STATE (inferior, 1 << STATE_RUNNING);
401   delay ();
402   i = tkill (inferior, SIGSTOP);
403   assert (i == 0);
404   /* Wait till it gets stopped otherwise we may get STATE_ENOENT below.  */
405   STATE (inferior, 1 << STATE_STOPPED);
406   delay ();
407   i = tkill (inferior, SIGUSR2);
408   assert (i == 0);
409   STATE (inferior, 1 << STATE_STOPPED);
410   delay ();
411   i = tkill (inferior, SIGCONT);
412   assert (i == 0);
413   /* Not just STATE_ZOMBIE as we can get spawn with waiter.  FIXME.  */
414   STATE (inferior, (1 << STATE_ENOENT) | (1 << STATE_ZOMBIE) | (1 << STATE_DEAD));
415   /* We would fail on: murder (inferior);  */
416 }
417
418 static void *pass (void *data, void *input)
419 {
420   struct spawner *param = data;
421   void (*input_func) (void) = input;
422
423   if (param != NULL)
424     return (*param->func) (param->data, input);
425
426   assert (input_func != NULL);
427   (*input_func) ();
428   /* NOTREACHED */
429   abort ();
430 }
431
432 static void *spawn_singlethreaded (void *data, void *input)
433 {
434   return pass (data, input);
435 }
436
437 static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg)
438 {
439   for (;;)
440     pause ();
441   /* NOTREACHED */
442   abort ();
443 }
444
445 static void *libpthread_handle;
446 static int (*libpthread_create_pointer) (pthread_t *thread,
447                                          const pthread_attr_t *attr,
448                                          void *(*start_routine) (void *),
449                                          void *arg);
450 static int (*libpthread_join_pointer) (pthread_t thread, void **value_ptr);
451
452 static void libpthread_open (void)
453 {
454   assert (libpthread_handle == NULL);
455
456   libpthread_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
457   assert (libpthread_handle != NULL);
458
459   libpthread_create_pointer = dlsym (libpthread_handle, "pthread_create");
460   assert (libpthread_create_pointer != NULL);
461   libpthread_join_pointer = dlsym (libpthread_handle, "pthread_join");
462   assert (libpthread_join_pointer != NULL);
463
464 }
465
466 static void libpthread_close (void)
467 {
468   int i;
469
470   assert (libpthread_handle != NULL);
471
472   i = dlclose (libpthread_handle);
473   assert (i == 0);
474   libpthread_handle = NULL;
475 }
476
477 static void *spawn_threaded_parent (void *data, void *input)
478 {
479   pthread_t thread;
480   int i;
481
482   assert (libpthread_create_pointer != NULL);
483   i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
484                                     NULL);
485   assert (i == 0);
486   return pass (data, input);
487 }
488
489 struct spawn_threaded_child_start
490   {
491     void *data;
492     void *input;
493   };
494
495 static void *spawn_threaded_child_start (void *arg_voidpointer)
496 {
497   struct spawn_threaded_child_start *arg = arg_voidpointer;
498
499   return pass (arg->data, arg->input);
500 }
501
502 static __attribute__((__noreturn__)) void *spawn_threaded_child (void *data, void *input)
503 {
504   pthread_t thread;
505   int i;
506   struct spawn_threaded_child_start arg_local;
507
508   arg_local.data = data;
509   arg_local.input = input;
510   assert (libpthread_create_pointer != NULL);
511   i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_child_start,
512                                     &arg_local);
513   assert (i == 0);
514   assert (libpthread_join_pointer != NULL);
515   i = (*libpthread_join_pointer) (thread, NULL);
516   assert (i == 0);
517
518   _exit (EXIT_SUCCESS);
519   /* NOTREACHED */
520   abort ();
521 }
522
523 static void body_maywaiter (void *(*child) (void *data, void *input),
524                             void *data, void *input)
525 {
526   struct spawner param_local;
527
528   param_local.func = child;
529   param_local.data = data;
530   body_spawner (spawn_without_waiter, &param_local, NULL);
531   body_spawner (spawn_with_waiter, &param_local, NULL);
532 }
533
534 static volatile unsigned long loops = 0;
535 static volatile int loops_print = 0;
536
537 static void handler_sigusr1 (int signo)
538 {
539   assert (signo == SIGUSR1);
540
541   loops_print++;
542 }
543
544 static __attribute__((__noreturn__)) void *tests_threaded (void *data, void *input)
545 {
546   libpthread_open ();
547
548   spawned_threads_count = 2;
549   body_maywaiter (spawn_threaded_parent, NULL, NULL);
550
551   spawned_threads_count = 2;
552   body_maywaiter (spawn_threaded_child, NULL, NULL);
553
554   libpthread_close ();
555
556   registry_cleanup ();
557   _exit (EXIT_SUCCESS);
558   /* NOTREACHED */
559   abort ();
560 }
561
562 int main (int argc, char **argv)
563 {
564   int loop = 0;
565   int i;
566
567 #ifdef MEASURE_STATE_PERFORMANCE
568   STATE (1, 1 << STATE_ZOMBIE);
569   return 0;
570 #endif /* MEASURE_STATE_PERFORMANCE */
571
572   if (argc == 1)
573     ;
574   else if (argc == 2 && strcmp (argv[1], "-l") == 0)
575     loop = 1;
576   else
577     abort ();
578
579   i = nice (10);
580   assert (i != -1);
581
582   atexit (registry_atexit);
583   signal (SIGINT, registry_handler);
584   signal (SIGABRT, registry_handler);
585
586   signal (SIGUSR1, handler_sigusr1);
587
588   do
589     {
590       pid_t pid_threaded, pid_threaded_got;
591       int status;
592
593       while (loops_print > 0)
594         {
595           printf ("%lu\n", loops);
596           loops_print--;
597         }
598
599       spawned_threads_count = 0;
600       body_maywaiter (spawn_singlethreaded, NULL, NULL);
601
602       /* We cannot rely on LIBPTHREAD_CLOSE as libpthread would be still loaded
603          with ATTACH_STATE_REDELIVERED_GET () reporting 1 for
604          SPAWN_SINGLETHREADED.  */
605       pid_threaded = spawn (tests_threaded, NULL, NULL, -1);
606       pid_threaded_got = waitpid (pid_threaded, &status, 0);
607       assert (pid_threaded_got == pid_threaded);
608       assert (!WIFSIGNALED (status));   /* Improve readability in the failed case.  */
609       assert (!WIFSTOPPED (status));    /* Improve readability in the failed case.  */
610       assert (WIFEXITED (status));
611       assert (WEXITSTATUS (status) == 0);
612       STATE (pid_threaded, 1 << STATE_ENOENT);
613       registry_remove (pid_threaded);
614
615       registry_cleanup ();
616       loops++;
617     }
618   /* Run at least twice to test libpthread_close ().  */
619   while (loop != 0 || loops == 1);
620
621   return EXIT_SUCCESS;
622 }