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