1 /* Copyright 2007, Red Hat Inc. */
14 #include <sys/syscall.h>
23 #define TIMEOUT_SECS 4
25 #define LOOPS_MIN 1000
28 #define tkill(tid, sig) syscall (SYS_tkill, (tid), (sig))
31 static volatile int spawned_threads_count; /* Set for the specific spawner. */
33 static struct attach_state_struct *attach_checked (pid_t pid, int redelivered_expect)
35 struct attach_state_struct *attach_state;
36 time_t timeout = time (NULL) + TIMEOUT_SECS;
39 STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING) | (1 << STATE_STOPPED));
42 attach_state = attach (pid);
43 if (redelivered_expect != attach_state_redelivered_get (attach_state))
45 fprintf (stderr, "Expecting redelivery of %d but found %d\n",
47 attach_state_redelivered_get (attach_state));
50 if (attach_state_threads_count_get (attach_state)
51 == spawned_threads_count)
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);
60 while (loops++ < LOOPS_MIN || time (NULL) < timeout);
62 /* FIXME: Why also STATE_STOPPED? */
63 STATE (pid, (1 << STATE_PTRACED) | (1 << STATE_STOPPED));
67 static void detach_checked (struct attach_state_struct *attach_state)
69 pid_t pid = attach_state_pid_get (attach_state);
71 if (attach_state_stopped_get (attach_state) != 0)
73 STATE (pid, 1 << STATE_STOPPED);
74 detach (attach_state);
75 STATE (pid, 1 << STATE_STOPPED);
79 STATE (pid, (1 << STATE_PTRACED));
80 detach (attach_state);
81 STATE (pid, ((1 << STATE_SLEEPING) | (1 << STATE_RUNNING)));
87 struct registry *next;
90 struct registry *registry_list;
92 static void registry_add (pid_t pid)
96 new = malloc (sizeof (*new));
99 new->next = registry_list;
103 static void registry_remove (pid_t pid)
105 struct registry **iter_pointer;
107 for (iter_pointer = ®istry_list; *iter_pointer != NULL;
108 iter_pointer = &(*iter_pointer)->next)
110 struct registry *found = *iter_pointer;
111 if (found->pid != pid)
114 *iter_pointer = found->next;
121 static void registry_atexit (void)
123 struct registry *iter;
125 for (iter = registry_list; iter != NULL; iter = iter->next)
127 tkill (iter->pid, SIGCONT);
128 tkill (iter->pid, SIGKILL);
129 kill (iter->pid, SIGKILL);
133 static void registry_cleanup (void)
135 struct registry *iter;
139 while ((pid = wait (NULL)) != -1)
141 for (iter = registry_list; iter != NULL; iter = iter->next)
142 if (iter->pid == pid)
144 assert (iter != NULL);
146 assert (errno == ECHILD);
147 while (registry_list)
149 iter = registry_list;
150 registry_list = iter->next;
155 static void registry_handler (int signo)
157 signal (signo, SIG_DFL);
162 static __attribute__((__noreturn__)) void child_pause (void)
170 static void child_alrm_handler (int signo)
172 assert (signo == SIGALRM);
176 static __attribute__((__noreturn__)) void child_alrm (void)
178 void (*handler_orig) (int signo);
184 handler_orig = signal (SIGALRM, child_alrm_handler);
185 assert (handler_orig == SIG_DFL);
188 i = sigprocmask (SIG_BLOCK, NULL, &oldset);
190 printf ("sigprocmask () -> sigismember (SIGALRM) == %d\n", sigismember (&oldset, SIGALRM));
199 static pid_t spawn (void *(*child) (void *data, void *input), void *data,
200 void *input, int fd_close)
216 i = close (fd_close);
228 STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING));
232 static void murder (pid_t pid)
241 i = kill (pid, SIGKILL);
244 pid_got = waitpid (pid, &status, 0);
245 if (!(pid_got == -1 && errno == ECHILD))
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);
254 STATE (pid, (1 << STATE_ENOENT) | (1 << STATE_ZOMBIE));
256 registry_remove (pid);
262 void *(*child) (void *data, void *input);
267 static __attribute__((__noreturn__)) void *child_spawner (void *param_voidpointer, void *input)
269 struct child_spawner *param = param_voidpointer;
271 ssize_t inferior_size;
274 inferior = spawn (param->child, param->data, input, param->fd);
276 inferior_size = write (param->fd, &inferior, sizeof (inferior));
277 assert (inferior_size == sizeof (inferior));
278 i = close (param->fd);
281 waitpid (inferior, NULL, 0);
282 _exit (EXIT_SUCCESS);
289 void *(*func) (void *data, void *input);
293 static void *spawn_with_waiter (void *data, void *input)
296 struct child_spawner param_local;
300 ssize_t inferior_size;
303 struct spawner *param = data;
305 assert (data != NULL);
310 param_local.child = param->func;
311 param_local.data = param->data;
312 param_local.fd = pipefds[1];
313 waiter = spawn (child_spawner, ¶m_local, input, pipefds[0]);
315 i = close (pipefds[1]);
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]);
324 registry_add (inferior);
326 return (void *) (unsigned long) inferior;
329 static void *spawn_without_waiter (void *data, void *input)
331 struct spawner *param = data;
333 return (void *) (unsigned long) spawn (param->func, param->data, input, -1);
336 static void body_spawner (void *(*child) (void *data, void *input), void *data,
340 struct attach_state_struct *attach_state;
343 assert (input == NULL);
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);
352 /* Attach to a process stopped by standard kill(2). */
353 inferior = (unsigned long) (*child) (data, child_pause);
355 i = kill (inferior, SIGSTOP);
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);
363 /* Attach to a process stopped by Linux specific tkill(2). */
364 inferior = (unsigned long) (*child) (data, child_pause);
366 i = tkill (inferior, SIGSTOP);
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);
374 /* Attach to a stopped process with already pending SIGALRM. */
375 inferior = (unsigned long) (*child) (data, child_alrm);
376 STATE (inferior, 1 << STATE_SLEEPING);
378 i = tkill (inferior, SIGSTOP);
380 /* Wait till it gets stopped otherwise we may get STATE_ENOENT below. */
381 STATE (inferior, 1 << STATE_STOPPED);
383 i = tkill (inferior, SIGALRM);
385 STATE (inferior, 1 << STATE_STOPPED);
386 /* FIXME: SIGALRM did not get redelivered? */
388 attach_state = attach_checked (inferior, SIGALRM);
390 attach_state = attach_checked (inferior, 0);
392 assert (attach_state_stopped_get (attach_state) == 1);
393 detach_checked (attach_state);
394 STATE (inferior, 1 << STATE_STOPPED);
396 i = tkill (inferior, SIGCONT);
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);
402 i = tkill (inferior, SIGSTOP);
404 /* Wait till it gets stopped otherwise we may get STATE_ENOENT below. */
405 STATE (inferior, 1 << STATE_STOPPED);
407 i = tkill (inferior, SIGUSR2);
409 STATE (inferior, 1 << STATE_STOPPED);
411 i = tkill (inferior, SIGCONT);
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); */
418 static void *pass (void *data, void *input)
420 struct spawner *param = data;
421 void (*input_func) (void) = input;
424 return (*param->func) (param->data, input);
426 assert (input_func != NULL);
432 static void *spawn_singlethreaded (void *data, void *input)
434 return pass (data, input);
437 static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg)
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 *),
450 static int (*libpthread_join_pointer) (pthread_t thread, void **value_ptr);
452 static void libpthread_open (void)
454 assert (libpthread_handle == NULL);
456 libpthread_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
457 assert (libpthread_handle != NULL);
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);
466 static void libpthread_close (void)
470 assert (libpthread_handle != NULL);
472 i = dlclose (libpthread_handle);
474 libpthread_handle = NULL;
477 static void *spawn_threaded_parent (void *data, void *input)
482 assert (libpthread_create_pointer != NULL);
483 i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
486 return pass (data, input);
489 struct spawn_threaded_child_start
495 static void *spawn_threaded_child_start (void *arg_voidpointer)
497 struct spawn_threaded_child_start *arg = arg_voidpointer;
499 return pass (arg->data, arg->input);
502 static __attribute__((__noreturn__)) void *spawn_threaded_child (void *data, void *input)
506 struct spawn_threaded_child_start arg_local;
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,
514 assert (libpthread_join_pointer != NULL);
515 i = (*libpthread_join_pointer) (thread, NULL);
518 _exit (EXIT_SUCCESS);
523 static void body_maywaiter (void *(*child) (void *data, void *input),
524 void *data, void *input)
526 struct spawner param_local;
528 param_local.func = child;
529 param_local.data = data;
530 body_spawner (spawn_without_waiter, ¶m_local, NULL);
531 body_spawner (spawn_with_waiter, ¶m_local, NULL);
534 static volatile unsigned long loops = 0;
535 static volatile int loops_print = 0;
537 static void handler_sigusr1 (int signo)
539 assert (signo == SIGUSR1);
544 static __attribute__((__noreturn__)) void *tests_threaded (void *data, void *input)
548 spawned_threads_count = 2;
549 body_maywaiter (spawn_threaded_parent, NULL, NULL);
551 spawned_threads_count = 2;
552 body_maywaiter (spawn_threaded_child, NULL, NULL);
557 _exit (EXIT_SUCCESS);
562 int main (int argc, char **argv)
567 #ifdef MEASURE_STATE_PERFORMANCE
568 STATE (1, 1 << STATE_ZOMBIE);
570 #endif /* MEASURE_STATE_PERFORMANCE */
574 else if (argc == 2 && strcmp (argv[1], "-l") == 0)
582 atexit (registry_atexit);
583 signal (SIGINT, registry_handler);
584 signal (SIGABRT, registry_handler);
586 signal (SIGUSR1, handler_sigusr1);
590 pid_t pid_threaded, pid_threaded_got;
593 while (loops_print > 0)
595 printf ("%lu\n", loops);
599 spawned_threads_count = 0;
600 body_maywaiter (spawn_singlethreaded, NULL, NULL);
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);
618 /* Run at least twice to test libpthread_close (). */
619 while (loop != 0 || loops == 1);