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