New state: STATE_DISK_SLEEP
[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 #if 0
183   int i;
184   sigset_t oldset;
185 #endif
186
187   /* Assumed already setup SIGALRM for CHILD_ALRM_HANDLER.  */
188
189 #if 0
190   i = sigprocmask (SIG_BLOCK, NULL, &oldset);
191   assert (i == 0);
192   printf ("sigprocmask () -> sigismember (SIGALRM) == %d\n", sigismember (&oldset, SIGALRM));
193 #endif
194
195   for (;;)
196     pause ();
197   /* NOTREACHED */
198   abort ();
199 }
200
201 static pid_t spawn (void *(*child) (void *data, void *input), void *data,
202                     void *input, int fd_close)
203 {
204   pid_t pid;
205
206   pid = fork();
207   switch (pid)
208     {
209       case -1:
210         perror ("fork()");
211         exit (EXIT_FAILURE);
212         /* NOTREACHED */
213       case 0:
214         if (fd_close != -1)
215           {
216             int i;
217
218             i = close (fd_close);
219             assert (i == 0);
220           }
221         child (data, input);
222         /* NOTREACHED */
223         abort ();
224       default:;
225         /* PASSTHRU */
226     }
227   /* Parent.  */
228
229   registry_add (pid);
230   STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING));
231   return pid;
232 }
233
234 static void murder (pid_t pid)
235 {
236   int i;
237   pid_t pid_got;
238   int status;
239
240   if (pid == 0)
241     return;
242
243   i = kill (pid, SIGKILL);
244   assert (i == 0);
245
246   pid_got = waitpid (pid, &status, 0);
247   if (!(pid_got == -1 && errno == ECHILD))
248     {
249       assert (pid_got == pid);
250       assert ((WIFSIGNALED (status) && (WTERMSIG (status) == SIGKILL
251                                         || WTERMSIG (status) == SIGUSR2))
252               || (WIFEXITED (status) && WEXITSTATUS (status) == 0));
253       STATE (pid, 1 << STATE_ENOENT);
254     }
255   else
256     STATE (pid, (1 << STATE_ENOENT) | (1 << STATE_ZOMBIE));
257
258   registry_remove (pid);
259 }
260
261
262 struct child_spawner
263   {
264     void *(*child) (void *data, void *input);
265     void *data;
266     int fd;
267   };
268
269 static __attribute__((__noreturn__)) void *child_spawner (void *param_voidpointer, void *input)
270 {
271   struct child_spawner *param = param_voidpointer;
272   pid_t inferior;
273   ssize_t inferior_size;
274   int i;
275
276   inferior = spawn (param->child, param->data, input, param->fd);
277
278   inferior_size = write (param->fd, &inferior, sizeof (inferior));
279   assert (inferior_size == sizeof (inferior));
280   i = close (param->fd);
281   assert (i == 0);
282
283   waitpid (inferior, NULL, 0);
284   _exit (EXIT_SUCCESS);
285   /* NOTREACHED */
286   abort ();
287 }
288
289 struct spawner
290   {
291     void *(*func) (void *data, void *input);
292     void *data;
293   };
294
295 static void *spawn_with_waiter (void *data, void *input)
296 {
297   pid_t waiter;
298   struct child_spawner param_local;
299   int pipefds[2];
300   int i;
301   pid_t inferior;
302   ssize_t inferior_size;
303   unsigned char buf;
304   ssize_t buf_size;
305   struct spawner *param = data;
306
307   assert (data != NULL);
308
309   i = pipe (pipefds);
310   assert (i == 0);
311
312   param_local.child = param->func;
313   param_local.data = param->data;
314   param_local.fd = pipefds[1];
315   waiter = spawn (child_spawner, &param_local, input, pipefds[0]);
316
317   i = close (pipefds[1]);
318   assert (i == 0);
319   inferior_size = read (pipefds[0], &inferior, sizeof (inferior));
320   assert (inferior_size == sizeof (inferior));
321   buf_size = read (pipefds[0], &buf, sizeof (buf));
322   assert (buf_size == 0);
323   i = close (pipefds[0]);
324   assert (i == 0);
325
326   registry_add (inferior);
327
328   return (void *) (unsigned long) inferior;
329 }
330
331 static void *spawn_without_waiter (void *data, void *input)
332 {
333   struct spawner *param = data;
334
335   return (void *) (unsigned long) spawn (param->func, param->data, input, -1);
336 }
337
338 static void body_spawner (void *(*child) (void *data, void *input), void *data,
339                           void *input)
340 {
341   pid_t inferior;
342   struct attach_state_struct *attach_state;
343   int i;
344   void (*handler_orig) (int signo);
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   /* Setup the handler already in the parent to avoid the child race.  */
379   handler_orig = signal (SIGALRM, child_alrm_handler);
380   assert (handler_orig == SIG_DFL);
381   inferior = (unsigned long) (*child) (data, child_alrm);
382   handler_orig = signal (SIGALRM, handler_orig);
383   assert (handler_orig == child_alrm_handler);
384   STATE (inferior, 1 << STATE_SLEEPING);
385   delay ();
386   i = tkill (inferior, SIGSTOP);
387   assert (i == 0);
388   /* Wait till it gets stopped otherwise we may get STATE_ENOENT below.  */
389   STATE (inferior, 1 << STATE_STOPPED);
390   delay ();
391   i = tkill (inferior, SIGALRM);
392   assert (i == 0);
393   STATE (inferior, 1 << STATE_STOPPED);
394   /* FIXME: SIGALRM did not get redelivered?  */
395 #if 0
396   attach_state = attach_checked (inferior, SIGALRM);
397 #else
398   attach_state = attach_checked (inferior, 0);
399 #endif
400   assert (attach_state_stopped_get (attach_state) == 1);
401   detach_checked (attach_state);
402   STATE (inferior, 1 << STATE_STOPPED);
403   delay ();
404   i = tkill (inferior, SIGCONT);
405   assert (i == 0);
406   /* This is a race, we may not prove the successful SIGALRM delivery by it.
407      Rather recheck it below.  */
408   STATE (inferior, 1 << STATE_RUNNING);
409   delay ();
410   i = tkill (inferior, SIGSTOP);
411   assert (i == 0);
412   /* Wait till it gets stopped otherwise we may get STATE_ENOENT below.  */
413   STATE (inferior, 1 << STATE_STOPPED);
414   delay ();
415   i = tkill (inferior, SIGUSR2);
416   assert (i == 0);
417   STATE (inferior, 1 << STATE_STOPPED);
418   delay ();
419   i = tkill (inferior, SIGCONT);
420   assert (i == 0);
421   /* Not just STATE_ZOMBIE as we can get spawn with waiter.  FIXME.  */
422   STATE (inferior, (1 << STATE_ENOENT) | (1 << STATE_ZOMBIE) | (1 << STATE_DEAD));
423   /* We would fail on: murder (inferior);  */
424 }
425
426 static void *pass (void *data, void *input)
427 {
428   struct spawner *param = data;
429   void (*input_func) (void) = input;
430
431   if (param != NULL)
432     return (*param->func) (param->data, input);
433
434   assert (input_func != NULL);
435   (*input_func) ();
436   /* NOTREACHED */
437   abort ();
438 }
439
440 static void *spawn_singlethreaded (void *data, void *input)
441 {
442   return pass (data, input);
443 }
444
445 static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg)
446 {
447   for (;;)
448     pause ();
449   /* NOTREACHED */
450   abort ();
451 }
452
453 static void *libpthread_handle;
454 static int (*libpthread_create_pointer) (pthread_t *thread,
455                                          const pthread_attr_t *attr,
456                                          void *(*start_routine) (void *),
457                                          void *arg);
458 static int (*libpthread_join_pointer) (pthread_t thread, void **value_ptr);
459
460 static void libpthread_open (void)
461 {
462   assert (libpthread_handle == NULL);
463
464   libpthread_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
465   assert (libpthread_handle != NULL);
466
467   libpthread_create_pointer = dlsym (libpthread_handle, "pthread_create");
468   assert (libpthread_create_pointer != NULL);
469   libpthread_join_pointer = dlsym (libpthread_handle, "pthread_join");
470   assert (libpthread_join_pointer != NULL);
471
472 }
473
474 static void libpthread_close (void)
475 {
476   int i;
477
478   assert (libpthread_handle != NULL);
479
480   i = dlclose (libpthread_handle);
481   assert (i == 0);
482   libpthread_handle = NULL;
483 }
484
485 static void *spawn_threaded_parent (void *data, void *input)
486 {
487   pthread_t thread;
488   int i;
489
490   assert (libpthread_create_pointer != NULL);
491   i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
492                                     NULL);
493   assert (i == 0);
494   return pass (data, input);
495 }
496
497 struct spawn_threaded_child_start
498   {
499     void *data;
500     void *input;
501   };
502
503 static void *spawn_threaded_child_start (void *arg_voidpointer)
504 {
505   struct spawn_threaded_child_start *arg = arg_voidpointer;
506
507   return pass (arg->data, arg->input);
508 }
509
510 static __attribute__((__noreturn__)) void *spawn_threaded_child (void *data, void *input)
511 {
512   pthread_t thread;
513   int i;
514   struct spawn_threaded_child_start arg_local;
515
516   arg_local.data = data;
517   arg_local.input = input;
518   assert (libpthread_create_pointer != NULL);
519   i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_child_start,
520                                     &arg_local);
521   assert (i == 0);
522   assert (libpthread_join_pointer != NULL);
523   i = (*libpthread_join_pointer) (thread, NULL);
524   assert (i == 0);
525
526   _exit (EXIT_SUCCESS);
527   /* NOTREACHED */
528   abort ();
529 }
530
531 static void body_maywaiter (void *(*child) (void *data, void *input),
532                             void *data, void *input)
533 {
534   struct spawner param_local;
535
536   param_local.func = child;
537   param_local.data = data;
538   body_spawner (spawn_without_waiter, &param_local, NULL);
539   body_spawner (spawn_with_waiter, &param_local, NULL);
540 }
541
542 static volatile unsigned long loops = 0;
543 static volatile int loops_print = 0;
544
545 static void handler_sigusr1 (int signo)
546 {
547   assert (signo == SIGUSR1);
548
549   loops_print++;
550 }
551
552 static __attribute__((__noreturn__)) void *tests_threaded (void *data, void *input)
553 {
554   libpthread_open ();
555
556   spawned_threads_count = 2;
557   body_maywaiter (spawn_threaded_parent, NULL, NULL);
558
559   spawned_threads_count = 2;
560   body_maywaiter (spawn_threaded_child, NULL, NULL);
561
562   libpthread_close ();
563
564   registry_cleanup ();
565   _exit (EXIT_SUCCESS);
566   /* NOTREACHED */
567   abort ();
568 }
569
570 int main (int argc, char **argv)
571 {
572   int loop = 0;
573   int i;
574
575 #ifdef MEASURE_STATE_PERFORMANCE
576   STATE (1, 1 << STATE_ZOMBIE);
577   return 0;
578 #endif /* MEASURE_STATE_PERFORMANCE */
579
580   if (argc == 1)
581     ;
582   else if (argc == 2 && strcmp (argv[1], "-l") == 0)
583     loop = 1;
584   else
585     abort ();
586
587   i = nice (10);
588   assert (i != -1);
589
590   atexit (registry_atexit);
591   signal (SIGINT, registry_handler);
592   signal (SIGABRT, registry_handler);
593
594   signal (SIGUSR1, handler_sigusr1);
595
596   do
597     {
598       pid_t pid_threaded, pid_threaded_got;
599       int status;
600
601       while (loops_print > 0)
602         {
603           printf ("%lu\n", loops);
604           loops_print--;
605         }
606
607       spawned_threads_count = 0;
608       body_maywaiter (spawn_singlethreaded, NULL, NULL);
609
610       /* We cannot rely on LIBPTHREAD_CLOSE as libpthread would be still loaded
611          with ATTACH_STATE_REDELIVERED_GET () reporting 1 for
612          SPAWN_SINGLETHREADED.  */
613       pid_threaded = spawn (tests_threaded, NULL, NULL, -1);
614       pid_threaded_got = waitpid (pid_threaded, &status, 0);
615       assert (pid_threaded_got == pid_threaded);
616       assert (!WIFSIGNALED (status));   /* Improve readability in the failed case.  */
617       assert (!WIFSTOPPED (status));    /* Improve readability in the failed case.  */
618       assert (WIFEXITED (status));
619       assert (WEXITSTATUS (status) == 0);
620       STATE (pid_threaded, 1 << STATE_ENOENT);
621       registry_remove (pid_threaded);
622
623       registry_cleanup ();
624       loops++;
625     }
626   /* Run at least twice to test libpthread_close ().  */
627   while (loop != 0 || loops == 1);
628
629   return EXIT_SUCCESS;
630 }