/* * Copyright (c) 2003, Intel Corporation. All rights reserved. * Created by: salwan.searty REMOVE-THIS AT intel DOT com * This file is licensed under the GPL license. For the full content * of this license, see the COPYING file at the top level of this * source tree. Assumption: The test assumes that this program is run under normal conditions, and not when the processor and other resources are too stressed. This program tries to verify two things: 1. sigsuspend() replaces the original signal mask (containing SIGUSR1) with the new signal mask (containing SIGUSR2.) This can be accomplished by having the child call sigsuspend, and then have the parent send the child a SIGUSR2 signal. The signal should remain pending while as long as the child is suspended. How do we verify that a signal is pending? Well, if it wasn't for the fact that the child is suspended, we could have easily called the sigpending() from the child process. Because the child is suspended, we have to somehow verify that the signal is pending using only the parent process. This is acheived by having the parent send the child another signal, one that will cause the child to resume execution. If the SIGUSR2 is only delivered after sigsuspend returns, then that means that SIGUSR2 has in fact been pending while the child was suspended, and therefore that proves that sigsuspend() did successfully temporarily replace the original signal mask with one containing only SIGUSR2. 2. The child process is suspended until the parent process delivers SIGUSR1. We verify this using the following rationale: Via the 3 seconds of sleep at the very start of the parent section of the code, the parent process allowed for enough time for the child process to complete execution and get to the "return 2" line at the very end of the child's code, but the parent didn't allow for any time in which the child may have been suspended. Because the child did recieve the signal that the parent later sent before the child finished executing, that had to have meant that the child was suspended for a while during it's execution. */ #include #include #include #include #include #include #include "posixtest.h" int SIGUSR1_called = 0; int SIGUSR2_called = 0; void handler(int signo) { if (signo == SIGUSR1) { printf("SIGUSR1 called. Inside handler\n"); SIGUSR1_called = 1; if (SIGUSR2_called == 1) { exit(1); } } else if (signo == SIGUSR2) { printf("SIGUSR2 called. Inside handler\n"); SIGUSR2_called = 1; if (SIGUSR1_called == 1) exit(0); else exit(1); } } int main() { pid_t pid; pid = fork(); if (pid == -1) { perror("fork"); return PTS_UNRESOLVED; } else if (pid == 0) { /* child */ sigset_t tempmask, originalmask; struct sigaction act; act.sa_handler = handler; act.sa_flags=0; sigemptyset(&act.sa_mask); sigemptyset(&tempmask); sigaddset(&tempmask, SIGUSR2); if (sigaction(SIGUSR1, &act, 0) == -1) { perror("Unexpected error while attempting to pre-conditions"); return PTS_UNRESOLVED; } if (sigaction(SIGUSR2, &act, 0) == -1) { perror("Unexpected error while attempting to pre-conditions"); return PTS_UNRESOLVED; } sigemptyset(&originalmask); sigaddset(&originalmask, SIGUSR1); sigprocmask(SIG_SETMASK, &originalmask, NULL); printf("suspending child\n"); if (sigsuspend(&tempmask) != -1) perror("sigsuspend error"); printf("returned from suspend\n"); sleep(1); return 2; } else { int s; int exit_status; /* parent */ sleep(3); printf("parent sending child a SIGUSR2 signal\n"); kill (pid, SIGUSR2); if (SIGUSR2_called == 1) { printf("Test FAILED: sigsuspend did not add SIGUSR2 to the temporary mask\n"); return PTS_FAIL; } printf("parent sending child a SIGUSR1 signal\n"); kill (pid, SIGUSR1); if (wait(&s) == -1) { perror("Unexpected error while setting up test " "pre-conditions"); return PTS_UNRESOLVED; } if (!WIFEXITED(s)) { printf("Test FAILED: Did not exit normally\n"); return PTS_FAIL; } exit_status = WEXITSTATUS(s); printf("Exit status from child is %d\n", exit_status); if (exit_status == 1) { printf("Test UNRESOLVED: Either sigsuspend did not successfully block SIGUSR2, OR sigsuspend returned before handling the signal SIGUSR1\n"); return PTS_UNRESOLVED; } if (exit_status == 2) { printf("Test FAILED: sigsuspend did not suspend the child\n"); return PTS_FAIL; } printf("Test PASSED\n"); return PTS_PASS; } }