Home | History | Annotate | Download | only in sigsuspend
      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 
     49 int SIGUSR1_called = 0;
     50 int SIGUSR2_called = 0;
     51 
     52 void 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 	} else if (signo == SIGUSR2) {
     61 		printf("SIGUSR2 called. Inside handler\n");
     62 		SIGUSR2_called = 1;
     63 		if (SIGUSR1_called == 1)
     64 			exit(0);
     65 		else
     66 			exit(1);
     67 	}
     68 }
     69 
     70 int main(void)
     71 {
     72 	pid_t pid;
     73 	pid = fork();
     74 
     75 	if (pid == 0) {
     76 		/* child */
     77 
     78 		sigset_t tempmask, originalmask;
     79 
     80 		struct sigaction act;
     81 
     82 		act.sa_handler = handler;
     83 		act.sa_flags = 0;
     84 		sigemptyset(&act.sa_mask);
     85 
     86 		sigemptyset(&tempmask);
     87 		sigaddset(&tempmask, SIGUSR2);
     88 
     89 		if (sigaction(SIGUSR1, &act, 0) == -1) {
     90 			perror
     91 			    ("Unexpected error while attempting to pre-conditions");
     92 			return PTS_UNRESOLVED;
     93 		}
     94 
     95 		if (sigaction(SIGUSR2, &act, 0) == -1) {
     96 			perror
     97 			    ("Unexpected error while attempting to pre-conditions");
     98 			return PTS_UNRESOLVED;
     99 		}
    100 
    101 		sigemptyset(&originalmask);
    102 		sigaddset(&originalmask, SIGUSR1);
    103 		sigprocmask(SIG_SETMASK, &originalmask, NULL);
    104 
    105 		printf("suspending child\n");
    106 		if (sigsuspend(&tempmask) != -1)
    107 			perror("sigsuspend error");
    108 
    109 		printf("returned from suspend\n");
    110 		sleep(1);
    111 		return 2;
    112 
    113 	} else {
    114 		int s;
    115 		int exit_status;
    116 
    117 		/* parent */
    118 		sleep(3);
    119 
    120 		printf("parent sending child a SIGUSR2 signal\n");
    121 		kill(pid, SIGUSR2);
    122 
    123 		if (SIGUSR2_called == 1) {
    124 			printf
    125 			    ("Test FAILED: sigsuspend did not add SIGUSR2 to the temporary mask\n");
    126 			return PTS_FAIL;
    127 		}
    128 		printf("parent sending child a SIGUSR1 signal\n");
    129 		kill(pid, SIGUSR1);
    130 
    131 		if (wait(&s) == -1) {
    132 			perror("Unexpected error while setting up test "
    133 			       "pre-conditions");
    134 			return PTS_UNRESOLVED;
    135 		}
    136 
    137 		if (!WIFEXITED(s)) {
    138 			printf("Test FAILED: Did not exit normally\n");
    139 			return PTS_FAIL;
    140 		}
    141 
    142 		exit_status = WEXITSTATUS(s);
    143 
    144 		printf("Exit status from child is %d\n", exit_status);
    145 
    146 		if (exit_status == 1) {
    147 			printf
    148 			    ("Test UNRESOLVED: Either sigsuspend did not successfully block SIGUSR2, OR sigsuspend returned before handling the signal SIGUSR1\n");
    149 			return PTS_UNRESOLVED;
    150 		}
    151 
    152 		if (exit_status == 2) {
    153 			printf
    154 			    ("Test FAILED: sigsuspend did not suspend the child\n");
    155 			return PTS_FAIL;
    156 		}
    157 
    158 		printf("Test PASSED\n");
    159 		return PTS_PASS;
    160 	}
    161 }
    162