1 /*
2  * Copyright 2016, Cyril Bur, IBM Corp.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version
7  * 2 of the License, or (at your option) any later version.
8  *
9  * Sending one self a signal should always get delivered.
10  */
11 
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <unistd.h>
19 
20 #include <altivec.h>
21 
22 #include "utils.h"
23 
24 #define MAX_ATTEMPT 500000
25 #define TIMEOUT 5
26 
27 extern long signal_self(pid_t pid, int sig);
28 
29 static sig_atomic_t signaled;
30 static sig_atomic_t fail;
31 
32 static void signal_handler(int sig)
33 {
34 	if (sig == SIGUSR1)
35 		signaled = 1;
36 	else
37 		fail = 1;
38 }
39 
40 static int test_signal()
41 {
42 	int i;
43 	struct sigaction act;
44 	pid_t ppid = getpid();
45 	pid_t pid;
46 
47 	act.sa_handler = signal_handler;
48 	act.sa_flags = 0;
49 	sigemptyset(&act.sa_mask);
50 	if (sigaction(SIGUSR1, &act, NULL) < 0) {
51 		perror("sigaction SIGUSR1");
52 		exit(1);
53 	}
54 	if (sigaction(SIGALRM, &act, NULL) < 0) {
55 		perror("sigaction SIGALRM");
56 		exit(1);
57 	}
58 
59 	/* Don't do this for MAX_ATTEMPT, its simply too long */
60 	for(i  = 0; i < 1000; i++) {
61 		pid = fork();
62 		if (pid == -1) {
63 			perror("fork");
64 			exit(1);
65 		}
66 		if (pid == 0) {
67 			signal_self(ppid, SIGUSR1);
68 			exit(1);
69 		} else {
70 			alarm(0); /* Disable any pending */
71 			alarm(2);
72 			while (!signaled && !fail)
73 				asm volatile("": : :"memory");
74 			if (!signaled) {
75 				fprintf(stderr, "Didn't get signal from child\n");
76 				FAIL_IF(1); /* For the line number */
77 			}
78 			/* Otherwise we'll loop too fast and fork() will eventually fail */
79 			waitpid(pid, NULL, 0);
80 		}
81 	}
82 
83 	for (i = 0; i < MAX_ATTEMPT; i++) {
84 		long rc;
85 
86 		alarm(0); /* Disable any pending */
87 		signaled = 0;
88 		alarm(TIMEOUT);
89 		rc = signal_self(ppid, SIGUSR1);
90 		if (rc) {
91 			fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
92 					i, fail, rc);
93 			FAIL_IF(1); /* For the line number */
94 		}
95 		while (!signaled && !fail)
96 			asm volatile("": : :"memory");
97 		if (!signaled) {
98 			fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
99 					i, fail, rc);
100 			FAIL_IF(1); /* For the line number */
101 		}
102 	}
103 
104 	return 0;
105 }
106 
107 int main(void)
108 {
109 	test_harness_set_timeout(300);
110 	return test_harness(test_signal, "signal");
111 }
112