/* * Copyright (c) 2002, Intel Corporation. All rights reserved. * Copyright (c) 2002, Jim Houston. All rights reserved. * Created by: julie.n.fleischer REMOVE-THIS AT intel DOT com * Patched by jim.houston REMOVE-THIS AT attbi 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. * Test that timers are not inherited across a fork(). * Steps: * 1. Set up a signal handler for timer in parent. * 2. Create timer using timer_create(). * 3. Activate timer using timer_settime(). * 4. Immediately fork a new process [Note: There is some risk here if * the system does not fork fast enough that there could be a false * failure. Times will be set large enough that this risk is minimized.] * 5. Set up a signal handler for the timer in the parent and ensure it * is not called by ensuring the child is able to sleep uninterrupted. * [Note: The delay to set up this handler could also cause false * results.] * * For this test clock CLOCK_REALTIME will be used. * * 12/17/02 - Applied Jim Houston's patch that fixed a bug. Parent originally * was set to return PTS_UNRESOLVED if nanosleep() was interrupted, * even though expected behavior is that it be interrupted once * to catch the signal. */ #include #include #include #include #include #include #include "posixtest.h" #define TIMERSEC 2 #define SLEEPDELTA 4 #define ACCEPTABLEDELTA 1 #define CHILDSUCCESS 1 #define CHILDFAILURE 0 void parenthandler(int signo) { printf("Expected - Caught signal\n"); } void handler(int signo) { printf("Not expected - Caught signal\n"); } int main(int argc, char *argv[]) { timer_t tid; struct sigaction actp; struct itimerspec its; int pid; actp.sa_handler=parenthandler; actp.sa_flags=0; its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; its.it_value.tv_sec = TIMERSEC; its.it_value.tv_nsec = 0; if (sigemptyset(&actp.sa_mask) == -1) { perror("Error calling sigemptyset\n"); return PTS_UNRESOLVED; } if (sigaction(SIGALRM, &actp, 0) == -1) { perror("Error calling sigaction\n"); return PTS_UNRESOLVED; } if (timer_create(CLOCK_REALTIME, NULL, &tid) != 0) { perror("timer_create() did not return success\n"); return PTS_UNRESOLVED; } if (timer_settime(tid, 0, &its, NULL) != 0) { perror("timer_settime() did not return success\n"); return PTS_UNRESOLVED; } if ((pid = fork()) == 0) { /* child here */ struct sigaction act; struct timespec ts, tsleft; act.sa_handler=handler; act.sa_flags=0; if (sigemptyset(&act.sa_mask) == -1) { perror("Error calling sigemptyset\n"); return CHILDFAILURE; } if (sigaction(SIGALRM, &act, 0) == -1) { perror("Error calling sigaction\n"); return CHILDFAILURE; } ts.tv_sec=TIMERSEC+SLEEPDELTA; ts.tv_nsec=0; if (nanosleep(&ts, &tsleft) == -1) { printf("child nanosleep() interrupted\n"); return CHILDFAILURE; } //nanosleep() not interrupted return CHILDSUCCESS; } else { /* parent here */ int i; struct timespec tsp, rem; /* * parent also sleeps to allow timer to expire */ tsp.tv_sec=TIMERSEC; tsp.tv_nsec=0; if (nanosleep(&tsp, &rem) == -1) { tsp = rem; if (nanosleep(&tsp, &rem) == -1) { printf("parent nanosleep() interrupted\n"); return PTS_UNRESOLVED; } } if (wait(&i) == -1) { perror("Error waiting for child to exit\n"); return PTS_UNRESOLVED; } if (WIFEXITED(i) && WEXITSTATUS(i)) { printf("Test PASSED\n"); return PTS_PASS; } else { printf("Child did not exit normally.\n"); printf("Test FAILED\n"); return PTS_FAIL; } } return PTS_UNRESOLVED; }