1570af302Sopenharmony_ci#include <string.h>
2570af302Sopenharmony_ci#include <signal.h>
3570af302Sopenharmony_ci#include <setjmp.h>
4570af302Sopenharmony_ci#include "test.h"
5570af302Sopenharmony_ci
6570af302Sopenharmony_ci#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
7570af302Sopenharmony_ci
8570af302Sopenharmony_ciint main(void)
9570af302Sopenharmony_ci{
10570af302Sopenharmony_ci	volatile int x = 0, r;
11570af302Sopenharmony_ci	jmp_buf jb;
12570af302Sopenharmony_ci	sigjmp_buf sjb;
13570af302Sopenharmony_ci	volatile sigset_t oldset;
14570af302Sopenharmony_ci	sigset_t set, set2;
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci	if (!setjmp(jb)) {
17570af302Sopenharmony_ci		x = 1;
18570af302Sopenharmony_ci		longjmp(jb, 1);
19570af302Sopenharmony_ci	}
20570af302Sopenharmony_ci	TEST(x==1, "setjmp/longjmp seems to have been bypassed\n");
21570af302Sopenharmony_ci
22570af302Sopenharmony_ci	x = 0;
23570af302Sopenharmony_ci	r = setjmp(jb);
24570af302Sopenharmony_ci	if (!x) {
25570af302Sopenharmony_ci		x = 1;
26570af302Sopenharmony_ci		longjmp(jb, 0);
27570af302Sopenharmony_ci	}
28570af302Sopenharmony_ci	TEST(r==1, "longjmp(jb, 0) caused setjmp to return %d\n", r);
29570af302Sopenharmony_ci
30570af302Sopenharmony_ci	sigemptyset(&set);
31570af302Sopenharmony_ci	sigaddset(&set, SIGUSR1);
32570af302Sopenharmony_ci	sigprocmask(SIG_UNBLOCK, &set, &set2);
33570af302Sopenharmony_ci	oldset = set2;
34570af302Sopenharmony_ci
35570af302Sopenharmony_ci	/* Improve the chances of catching failure of sigsetjmp to
36570af302Sopenharmony_ci	 * properly save the signal mask in the sigjmb_buf. */
37570af302Sopenharmony_ci	memset(&sjb, -1, sizeof sjb);
38570af302Sopenharmony_ci
39570af302Sopenharmony_ci	if (!sigsetjmp(sjb, 1)) {
40570af302Sopenharmony_ci		sigemptyset(&set);
41570af302Sopenharmony_ci		sigaddset(&set, SIGUSR1);
42570af302Sopenharmony_ci		sigprocmask(SIG_BLOCK, &set, 0);
43570af302Sopenharmony_ci		siglongjmp(sjb, 1);
44570af302Sopenharmony_ci	}
45570af302Sopenharmony_ci	set = oldset;
46570af302Sopenharmony_ci	sigprocmask(SIG_SETMASK, &set, &set2);
47570af302Sopenharmony_ci	TEST(sigismember(&set2, SIGUSR1)==0, "siglongjmp failed to restore mask\n");
48570af302Sopenharmony_ci
49570af302Sopenharmony_ci	sigemptyset(&set);
50570af302Sopenharmony_ci	sigaddset(&set, SIGUSR1);
51570af302Sopenharmony_ci	sigprocmask(SIG_UNBLOCK, &set, &set2);
52570af302Sopenharmony_ci	oldset = set2;
53570af302Sopenharmony_ci
54570af302Sopenharmony_ci	if (!sigsetjmp(sjb, 0)) {
55570af302Sopenharmony_ci		sigemptyset(&set);
56570af302Sopenharmony_ci		sigaddset(&set, SIGUSR1);
57570af302Sopenharmony_ci		sigprocmask(SIG_BLOCK, &set, 0);
58570af302Sopenharmony_ci		siglongjmp(sjb, 1);
59570af302Sopenharmony_ci	}
60570af302Sopenharmony_ci	set = oldset;
61570af302Sopenharmony_ci	sigprocmask(SIG_SETMASK, &set, &set2);
62570af302Sopenharmony_ci	TEST(sigismember(&set2, SIGUSR1)==1, "siglongjmp incorrectly restored mask\n");
63570af302Sopenharmony_ci
64570af302Sopenharmony_ci	return t_status;
65570af302Sopenharmony_ci}
66