1// commit: 370f78f2c80c64b7b0780a01e672494a26b5678e 2011-03-09
2// commit: 0bed7e0acfd34e3fb63ca0e4d99b7592571355a9 2011-03-09
3// raise should be robust against async fork in a signal handler
4#include <pthread.h>
5#include <signal.h>
6#include <errno.h>
7#include <string.h>
8#include <sys/wait.h>
9#include <unistd.h>
10#include "test.h"
11#define SIGNUM 40
12static volatile int c0;
13static volatile int c1;
14static volatile int child;
15
16static void handler0(int sig)
17{
18	c0++;
19}
20
21static void handler1(int sig)
22{
23	c1++;
24	switch (fork()) {
25	case 0: child=1; break;
26	case -1: t_error("fork failed: %s\n", strerror(errno));
27	}
28}
29
30static void *start(void *arg)
31{
32	int i,r,s;
33
34	for (i = 0; i < 1000; i++) {
35		r = raise(SIGNUM);
36		if (r)
37			t_error("raise failed: %s\n", strerror(errno));
38	}
39	if (c0 != 1000)
40		t_error("lost signals: got %d, wanted 1000 (ischild %d forks %d)\n", c0, child, c1);
41	if (child)
42		_exit(t_status);
43
44	/* make sure we got all pthread_kills, then wait the forked children */
45	while (c1 < 100);
46	for (i = 0; i < 100; i++) {
47		r = wait(&s);
48		if (r == -1)
49			t_error("wait failed: %s\n", strerror(errno));
50		else if (!WIFEXITED(s) || WTERMSIG(s))
51			t_error("child failed: pid:%d status:%d\n", r, s);
52	}
53	return 0;
54}
55
56int main(void)
57{
58	pthread_t t;
59	void *p;
60	int r, i, s;
61
62	if (signal(SIGNUM, handler0) == SIG_ERR)
63		t_error("registering signal handler failed: %s\n", strerror(errno));
64	if (signal(SIGNUM+1, handler1) == SIG_ERR)
65		t_error("registering signal handler failed: %s\n", strerror(errno));
66
67	r = pthread_create(&t, 0, start, 0);
68	if (r)
69		t_error("pthread_create failed: %s\n", strerror(r));
70	for (i = 0; i < 100; i++) {
71		r = pthread_kill(t, SIGNUM+1);
72		if (r)
73			t_error("phread_kill failed: %s\n", strerror(r));
74	}
75	r = pthread_join(t,&p);
76	if (r)
77		t_error("pthread_join failed: %s\n", strerror(r));
78	return t_status;
79}
80