1cbdddcfb32883a37e873907602d34bac523e3eadsewardj/*
2cbdddcfb32883a37e873907602d34bac523e3eadsewardj   Test pending signals
3cbdddcfb32883a37e873907602d34bac523e3eadsewardj
4cbdddcfb32883a37e873907602d34bac523e3eadsewardj   1. Signals should remain pending while blocked, and not delivered early
5cbdddcfb32883a37e873907602d34bac523e3eadsewardj
6cbdddcfb32883a37e873907602d34bac523e3eadsewardj   2. When unblocking the signal, the signal should have been delivered
7cbdddcfb32883a37e873907602d34bac523e3eadsewardj      by the time sigprocmask syscall is complete.
8cbdddcfb32883a37e873907602d34bac523e3eadsewardj */
9cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <signal.h>
10cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <stdio.h>
11cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <unistd.h>
12cbdddcfb32883a37e873907602d34bac523e3eadsewardj#include <stdlib.h>
136cc2247cdfab852131fd392fb041ed07cd9117c6njn#include "config.h"
14cbdddcfb32883a37e873907602d34bac523e3eadsewardj
15cbdddcfb32883a37e873907602d34bac523e3eadsewardjstatic volatile int gotsig = 0;
16cbdddcfb32883a37e873907602d34bac523e3eadsewardjstatic volatile int early = 1;
17cbdddcfb32883a37e873907602d34bac523e3eadsewardj
18cbdddcfb32883a37e873907602d34bac523e3eadsewardjstatic void handler(int sig)
19cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
206cc2247cdfab852131fd392fb041ed07cd9117c6njn	printf("4: got signal %s\n",
216cc2247cdfab852131fd392fb041ed07cd9117c6njn		( sig == SIGUSR1 ? "SIGUSR1" : "unexpected signal" ));
22cbdddcfb32883a37e873907602d34bac523e3eadsewardj
23cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (sig != SIGUSR1) {
24cbdddcfb32883a37e873907602d34bac523e3eadsewardj		fprintf(stderr, "FAILED: got signal %d instead\n", sig);
25cbdddcfb32883a37e873907602d34bac523e3eadsewardj		exit(1);
26cbdddcfb32883a37e873907602d34bac523e3eadsewardj	}
27cbdddcfb32883a37e873907602d34bac523e3eadsewardj
28cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (early) {
29cbdddcfb32883a37e873907602d34bac523e3eadsewardj		fprintf(stderr, "FAILED: signal delivered early (in handler)\n");
30cbdddcfb32883a37e873907602d34bac523e3eadsewardj		exit(1);
31cbdddcfb32883a37e873907602d34bac523e3eadsewardj	}
32cbdddcfb32883a37e873907602d34bac523e3eadsewardj
33cbdddcfb32883a37e873907602d34bac523e3eadsewardj	gotsig = 1;
34cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
35cbdddcfb32883a37e873907602d34bac523e3eadsewardj
36cbdddcfb32883a37e873907602d34bac523e3eadsewardjint main()
37cbdddcfb32883a37e873907602d34bac523e3eadsewardj{
38cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigset_t all;
39cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigset_t sigusr1;
40cbdddcfb32883a37e873907602d34bac523e3eadsewardj
41cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigfillset(&all);
42cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigemptyset(&sigusr1);
43cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigaddset(&sigusr1, SIGUSR1);
44cbdddcfb32883a37e873907602d34bac523e3eadsewardj
45cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigprocmask(SIG_BLOCK, &all, NULL);
46cbdddcfb32883a37e873907602d34bac523e3eadsewardj
47cbdddcfb32883a37e873907602d34bac523e3eadsewardj	signal(SIGUSR1, handler);
48cff47f6d07be8dcdc8e12d57f8248b5c1cef21f4njn	signal(SIGHUP,  handler);
49cbdddcfb32883a37e873907602d34bac523e3eadsewardj
50cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("1: sending signal\n");
51cbdddcfb32883a37e873907602d34bac523e3eadsewardj	kill(getpid(), SIGUSR1);
52cff47f6d07be8dcdc8e12d57f8248b5c1cef21f4njn	kill(getpid(), SIGHUP);
53cbdddcfb32883a37e873907602d34bac523e3eadsewardj
54cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("2: sleeping\n");
55cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sleep(1);
56cbdddcfb32883a37e873907602d34bac523e3eadsewardj
57cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (gotsig) {
58cbdddcfb32883a37e873907602d34bac523e3eadsewardj		fprintf(stderr, "FAILED: signal delivered too early\n");
59cbdddcfb32883a37e873907602d34bac523e3eadsewardj		return 1;
60cbdddcfb32883a37e873907602d34bac523e3eadsewardj	}
61cbdddcfb32883a37e873907602d34bac523e3eadsewardj
62cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("3: unblocking\n");
63cbdddcfb32883a37e873907602d34bac523e3eadsewardj	early = 0;
64cbdddcfb32883a37e873907602d34bac523e3eadsewardj	sigprocmask(SIG_UNBLOCK, &sigusr1, NULL);
65cbdddcfb32883a37e873907602d34bac523e3eadsewardj
66cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("5: unblocked...\n");
67cbdddcfb32883a37e873907602d34bac523e3eadsewardj	if (!gotsig) {
68cbdddcfb32883a37e873907602d34bac523e3eadsewardj		fprintf(stderr, "FAILED: signal not delivered\n");
69cbdddcfb32883a37e873907602d34bac523e3eadsewardj		return 1;
70cbdddcfb32883a37e873907602d34bac523e3eadsewardj	}
71cbdddcfb32883a37e873907602d34bac523e3eadsewardj
72cff47f6d07be8dcdc8e12d57f8248b5c1cef21f4njn	printf("6: checking SIGHUP still pending...\n");
736cc2247cdfab852131fd392fb041ed07cd9117c6njn#	if HAVE_SIGWAITINFO
746cc2247cdfab852131fd392fb041ed07cd9117c6njn	{
756cc2247cdfab852131fd392fb041ed07cd9117c6njn		siginfo_t info;
766cc2247cdfab852131fd392fb041ed07cd9117c6njn		if (sigwaitinfo(&all, &info) == -1) {
776cc2247cdfab852131fd392fb041ed07cd9117c6njn			perror("FAILED: sigwaitinfo failed");
786cc2247cdfab852131fd392fb041ed07cd9117c6njn			return 1;
796cc2247cdfab852131fd392fb041ed07cd9117c6njn		}
80cff47f6d07be8dcdc8e12d57f8248b5c1cef21f4njn		if (info.si_signo != SIGHUP) {
81cff47f6d07be8dcdc8e12d57f8248b5c1cef21f4njn			fprintf(stderr, "FAILED: SIGHUP not still pending; got signal %d\n",
826cc2247cdfab852131fd392fb041ed07cd9117c6njn				info.si_signo);
836cc2247cdfab852131fd392fb041ed07cd9117c6njn			return 1;
846cc2247cdfab852131fd392fb041ed07cd9117c6njn		}
85cbdddcfb32883a37e873907602d34bac523e3eadsewardj	}
866cc2247cdfab852131fd392fb041ed07cd9117c6njn#	endif
87cbdddcfb32883a37e873907602d34bac523e3eadsewardj
88cbdddcfb32883a37e873907602d34bac523e3eadsewardj	printf("OK\n");
89cbdddcfb32883a37e873907602d34bac523e3eadsewardj	return 0;
90cbdddcfb32883a37e873907602d34bac523e3eadsewardj}
91