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  Steps:
     12  1. Fork() a child process. In the child, add SIGUSR1 to the process's signal mask.
     13     This is its original signal mask. Now suspend the child, passing sigsuspend another
     14     signal mask. One that doesn't contain SIGUSR1, but contains SIGUSR2.
     15  2. From the parent, send the child a SIGUSR1 signal so that the child returns from
     16     suspension.
     17  3. Once the sigsuspend returns, have the child probe the signal mask using the is_changed()
     18     function which basically verifies that the signal mask is restored to what it was originally
     19     before the call to sigsuspend. I.e. SIGUSR1 in the mask and SIGUSR2 not in the mask. Have
     20     the child return to the parent process with:
     21     - a return value of 1 if the original signal mask was not restored, or
     22     - a return value of 0 if the original signal mask was successfully restored.
     23  4. Finally from the parent, return a PTS_PASS if recieved the return value of the child was not
     24     a 1.
     25 
     26 */
     27 
     28 #include <signal.h>
     29 #include <sys/types.h>
     30 #include <sys/wait.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <unistd.h>
     34 #include "posixtest.h"
     35 
     36 #define NUMSIGNALS (sizeof(siglist) / sizeof(siglist[0]))
     37 
     38 void handler(int signo)
     39 {
     40 }
     41 
     42 int is_changed(sigset_t set, int sig)
     43 {
     44 
     45 	int i;
     46 	int siglist[] = { SIGABRT, SIGALRM, SIGBUS, SIGCHLD,
     47 		SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT,
     48 		SIGPIPE, SIGQUIT, SIGSEGV,
     49 		SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU,
     50 		SIGUSR1, SIGUSR2,
     51 #ifdef SIGPOLL
     52 		SIGPOLL,
     53 #endif
     54 #ifdef SIGPROF
     55 		SIGPROF,
     56 #endif
     57 		SIGSYS,
     58 		SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ
     59 	};
     60 
     61 	if (sigismember(&set, sig) != 1) {
     62 		return 1;
     63 	}
     64 	for (i = 0; i < NUMSIGNALS; i++) {
     65 		if ((siglist[i] != sig)) {
     66 			if (sigismember(&set, siglist[i]) != 0) {
     67 				return 1;
     68 			}
     69 		}
     70 	}
     71 	return 0;
     72 }
     73 
     74 int main(void)
     75 {
     76 	pid_t pid;
     77 	pid = fork();
     78 
     79 	if (pid == 0) {
     80 		/* child */
     81 
     82 		sigset_t tempmask, originalmask, currentmask;
     83 
     84 		struct sigaction act;
     85 
     86 		act.sa_handler = handler;
     87 		act.sa_flags = 0;
     88 		sigemptyset(&act.sa_mask);
     89 
     90 		sigemptyset(&tempmask);
     91 		sigaddset(&tempmask, SIGUSR2);
     92 
     93 		if (sigaction(SIGUSR1, &act, 0) == -1) {
     94 			perror
     95 			    ("Unexpected error while attempting to pre-conditions");
     96 			return PTS_UNRESOLVED;
     97 		}
     98 
     99 		sigemptyset(&originalmask);
    100 		sigaddset(&originalmask, SIGUSR1);
    101 		sigprocmask(SIG_SETMASK, &originalmask, NULL);
    102 
    103 		printf("suspending child\n");
    104 		if (sigsuspend(&tempmask) != -1)
    105 			perror("sigsuspend error");
    106 
    107 		printf("returned from suspend\n");
    108 
    109 		sigprocmask(SIG_SETMASK, NULL, &currentmask);
    110 
    111 		if (is_changed(currentmask, SIGUSR1) != 0) {
    112 			printf
    113 			    ("signal mask was not restored properly after sigsuspend returned\n");
    114 			return 1;
    115 		}
    116 		return 0;
    117 
    118 	} else {
    119 		int s;
    120 		int exit_status;
    121 
    122 		/* parent */
    123 		sleep(1);
    124 
    125 		printf("parent sending child a SIGUSR1 signal\n");
    126 		kill(pid, SIGUSR1);
    127 
    128 		if (wait(&s) == -1) {
    129 			perror("Unexpected error while setting up test "
    130 			       "pre-conditions");
    131 			return PTS_UNRESOLVED;
    132 		}
    133 
    134 		if (!WIFEXITED(s)) {
    135 			printf("Test FAILED: Did not exit normally\n");
    136 			return PTS_FAIL;
    137 		}
    138 
    139 		exit_status = WEXITSTATUS(s);
    140 
    141 		printf("Exit status from child is %d\n", exit_status);
    142 
    143 		if (exit_status == 1) {
    144 			return PTS_FAIL;
    145 		}
    146 
    147 		printf("Test PASSED\n");
    148 		return PTS_PASS;
    149 	}
    150 }
    151