1570af302Sopenharmony_ci// commit: 370f78f2c80c64b7b0780a01e672494a26b5678e 2011-03-09
2570af302Sopenharmony_ci// commit: 0bed7e0acfd34e3fb63ca0e4d99b7592571355a9 2011-03-09
3570af302Sopenharmony_ci// raise should be robust against async fork in a signal handler
4570af302Sopenharmony_ci#include <pthread.h>
5570af302Sopenharmony_ci#include <signal.h>
6570af302Sopenharmony_ci#include <errno.h>
7570af302Sopenharmony_ci#include <string.h>
8570af302Sopenharmony_ci#include <sys/wait.h>
9570af302Sopenharmony_ci#include <unistd.h>
10570af302Sopenharmony_ci#include "test.h"
11570af302Sopenharmony_ci#define SIGNUM 40
12570af302Sopenharmony_cistatic volatile int c0;
13570af302Sopenharmony_cistatic volatile int c1;
14570af302Sopenharmony_cistatic volatile int child;
15570af302Sopenharmony_ci
16570af302Sopenharmony_cistatic void handler0(int sig)
17570af302Sopenharmony_ci{
18570af302Sopenharmony_ci	c0++;
19570af302Sopenharmony_ci}
20570af302Sopenharmony_ci
21570af302Sopenharmony_cistatic void handler1(int sig)
22570af302Sopenharmony_ci{
23570af302Sopenharmony_ci	c1++;
24570af302Sopenharmony_ci	switch (fork()) {
25570af302Sopenharmony_ci	case 0: child=1; break;
26570af302Sopenharmony_ci	case -1: t_error("fork failed: %s\n", strerror(errno));
27570af302Sopenharmony_ci	}
28570af302Sopenharmony_ci}
29570af302Sopenharmony_ci
30570af302Sopenharmony_cistatic void *start(void *arg)
31570af302Sopenharmony_ci{
32570af302Sopenharmony_ci	int i,r,s;
33570af302Sopenharmony_ci
34570af302Sopenharmony_ci	for (i = 0; i < 1000; i++) {
35570af302Sopenharmony_ci		r = raise(SIGNUM);
36570af302Sopenharmony_ci		if (r)
37570af302Sopenharmony_ci			t_error("raise failed: %s\n", strerror(errno));
38570af302Sopenharmony_ci	}
39570af302Sopenharmony_ci	if (c0 != 1000)
40570af302Sopenharmony_ci		t_error("lost signals: got %d, wanted 1000 (ischild %d forks %d)\n", c0, child, c1);
41570af302Sopenharmony_ci	if (child)
42570af302Sopenharmony_ci		_exit(t_status);
43570af302Sopenharmony_ci
44570af302Sopenharmony_ci	/* make sure we got all pthread_kills, then wait the forked children */
45570af302Sopenharmony_ci	while (c1 < 100);
46570af302Sopenharmony_ci	for (i = 0; i < 100; i++) {
47570af302Sopenharmony_ci		r = wait(&s);
48570af302Sopenharmony_ci		if (r == -1)
49570af302Sopenharmony_ci			t_error("wait failed: %s\n", strerror(errno));
50570af302Sopenharmony_ci		else if (!WIFEXITED(s) || WTERMSIG(s))
51570af302Sopenharmony_ci			t_error("child failed: pid:%d status:%d\n", r, s);
52570af302Sopenharmony_ci	}
53570af302Sopenharmony_ci	return 0;
54570af302Sopenharmony_ci}
55570af302Sopenharmony_ci
56570af302Sopenharmony_ciint main(void)
57570af302Sopenharmony_ci{
58570af302Sopenharmony_ci	pthread_t t;
59570af302Sopenharmony_ci	void *p;
60570af302Sopenharmony_ci	int r, i, s;
61570af302Sopenharmony_ci
62570af302Sopenharmony_ci	if (signal(SIGNUM, handler0) == SIG_ERR)
63570af302Sopenharmony_ci		t_error("registering signal handler failed: %s\n", strerror(errno));
64570af302Sopenharmony_ci	if (signal(SIGNUM+1, handler1) == SIG_ERR)
65570af302Sopenharmony_ci		t_error("registering signal handler failed: %s\n", strerror(errno));
66570af302Sopenharmony_ci
67570af302Sopenharmony_ci	r = pthread_create(&t, 0, start, 0);
68570af302Sopenharmony_ci	if (r)
69570af302Sopenharmony_ci		t_error("pthread_create failed: %s\n", strerror(r));
70570af302Sopenharmony_ci	for (i = 0; i < 100; i++) {
71570af302Sopenharmony_ci		r = pthread_kill(t, SIGNUM+1);
72570af302Sopenharmony_ci		if (r)
73570af302Sopenharmony_ci			t_error("phread_kill failed: %s\n", strerror(r));
74570af302Sopenharmony_ci	}
75570af302Sopenharmony_ci	r = pthread_join(t,&p);
76570af302Sopenharmony_ci	if (r)
77570af302Sopenharmony_ci		t_error("pthread_join failed: %s\n", strerror(r));
78570af302Sopenharmony_ci	return t_status;
79570af302Sopenharmony_ci}
80