1/* 2 * Copyright (c) 2003, Intel Corporation. All rights reserved. 3 * Created by: salwan.searty REMOVE-THIS AT intel DOT com 4 * This file is licensed under the GPL license. For the full content 5 * of this license, see the COPYING file at the top level of this 6 * source tree. 7 8 Assumption: The test assumes that this program is run under normal conditions, 9 and not when the processor and other resources are too stressed. 10 11 This program tries to verify two things: 12 13 1. sigsuspend() replaces the original signal mask (containing SIGUSR1) 14 with the new signal mask (containing SIGUSR2.) This can be accomplished 15 by having the child call sigsuspend, and then have the parent send the 16 child a SIGUSR2 signal. The signal should remain pending while as long 17 as the child is suspended. How do we verify that a signal is pending? 18 Well, if it wasn't for the fact that the child is suspended, we could 19 have easily called the sigpending() from the child process. Because 20 the child is suspended, we have to somehow verify that the signal is 21 pending using only the parent process. This is acheived by having the 22 parent send the child another signal, one that will cause the child to 23 resume execution. If the SIGUSR2 is only delivered after sigsuspend 24 returns, then that means that SIGUSR2 has in fact been pending while 25 the child was suspended, and therefore that proves that sigsuspend() 26 did successfully temporarily replace the original signal mask with one 27 containing only SIGUSR2. 28 29 2. The child process is suspended until the parent process delivers 30 SIGUSR1. We verify this using the following rationale: Via the 3 seconds of 31 sleep at the very start of the parent section of the code, the parent 32 process allowed for enough time for the child process to complete execution 33 and get to the "return 2" line at the very end of the child's code, but the 34 parent didn't allow for any time in which the child may have been suspended. 35 Because the child did recieve the signal that the parent later sent before 36 the child finished executing, that had to have meant that the child was 37 suspended for a while during it's execution. 38 39*/ 40 41#include <signal.h> 42#include <sys/types.h> 43#include <sys/wait.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <unistd.h> 47#include "posixtest.h" 48 49int SIGUSR1_called = 0; 50int SIGUSR2_called = 0; 51 52void handler(int signo) 53{ 54 if (signo == SIGUSR1) { 55 printf("SIGUSR1 called. Inside handler\n"); 56 SIGUSR1_called = 1; 57 if (SIGUSR2_called == 1) { 58 exit(1); 59 } 60 } 61 else if (signo == SIGUSR2) { 62 printf("SIGUSR2 called. Inside handler\n"); 63 SIGUSR2_called = 1; 64 if (SIGUSR1_called == 1) 65 exit(0); 66 else 67 exit(1); 68 } 69} 70 71int main() 72{ 73 pid_t pid; 74 pid = fork(); 75 76 if (pid == 0) { 77 /* child */ 78 79 sigset_t tempmask, originalmask; 80 81 struct sigaction act; 82 83 act.sa_handler = handler; 84 act.sa_flags=0; 85 sigemptyset(&act.sa_mask); 86 87 sigemptyset(&tempmask); 88 sigaddset(&tempmask, SIGUSR2); 89 90 if (sigaction(SIGUSR1, &act, 0) == -1) { 91 perror("Unexpected error while attempting to pre-conditions"); 92 return PTS_UNRESOLVED; 93 } 94 95 if (sigaction(SIGUSR2, &act, 0) == -1) { 96 perror("Unexpected error while attempting to pre-conditions"); 97 return PTS_UNRESOLVED; 98 } 99 100 sigemptyset(&originalmask); 101 sigaddset(&originalmask, SIGUSR1); 102 sigprocmask(SIG_SETMASK, &originalmask, NULL); 103 104 printf("suspending child\n"); 105 if (sigsuspend(&tempmask) != -1) 106 perror("sigsuspend error"); 107 108 printf("returned from suspend\n"); 109 sleep(1); 110 return 2; 111 112 } else { 113 int s; 114 int exit_status; 115 116 /* parent */ 117 sleep(3); 118 119 printf("parent sending child a SIGUSR2 signal\n"); 120 kill (pid, SIGUSR2); 121 122 if (SIGUSR2_called == 1) { 123 printf("Test FAILED: sigsuspend did not add SIGUSR2 to the temporary mask\n"); 124 return PTS_FAIL; 125 } 126 printf("parent sending child a SIGUSR1 signal\n"); 127 kill (pid, SIGUSR1); 128 129 if (wait(&s) == -1) { 130 perror("Unexpected error while setting up test " 131 "pre-conditions"); 132 return PTS_UNRESOLVED; 133 } 134 135 if (!WIFEXITED(s)) { 136 printf("Test FAILED: Did not exit normally\n"); 137 return PTS_FAIL; 138 } 139 140 exit_status = WEXITSTATUS(s); 141 142 printf("Exit status from child is %d\n", exit_status); 143 144 if (exit_status == 1) { 145 printf("Test UNRESOLVED: Either sigsuspend did not successfully block SIGUSR2, OR sigsuspend returned before handling the signal SIGUSR1\n"); 146 return PTS_UNRESOLVED; 147 } 148 149 if (exit_status == 2) { 150 printf("Test FAILED: sigsuspend did not suspend the child\n"); 151 return PTS_FAIL; 152 } 153 154 printf("Test PASSED\n"); 155 return PTS_PASS; 156 } 157} 158