1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Test Description: 22 * Verify that nanosleep() will fail to suspend the execution 23 * of a process for a specified time if interrupted by a non-blocked signal. 24 * 25 * Expected Result: 26 * nanosleep() should return with -1 value and sets errno to EINTR. 27 */ 28 29 #include <errno.h> 30 #include <unistd.h> 31 #include <fcntl.h> 32 #include <time.h> 33 #include <sys/wait.h> 34 35 #include "test.h" 36 #include "safe_macros.h" 37 38 char *TCID = "nanosleep03"; 39 int TST_TOTAL = 1; 40 41 static void do_child(void); 42 static void setup(void); 43 static void sig_handler(); 44 45 int main(int ac, char **av) 46 { 47 int lc; 48 pid_t cpid; 49 int status; 50 51 tst_parse_opts(ac, av, NULL, NULL); 52 53 #ifdef UCLINUX 54 maybe_run_child(&do_child, "dddd", &timereq.tv_sec, &timereq.tv_nsec, 55 &timerem.tv_sec, &timerem.tv_nsec); 56 #endif 57 58 setup(); 59 60 for (lc = 0; TEST_LOOPING(lc); lc++) { 61 tst_count = 0; 62 63 /* 64 * Creat a child process and suspend its 65 * execution using nanosleep() 66 */ 67 if ((cpid = FORK_OR_VFORK()) == -1) 68 tst_brkm(TBROK, NULL, "fork() failed"); 69 70 if (cpid == 0) { 71 #ifdef UCLINUX 72 if (self_exec(av[0], "dddd", 73 timereq.tv_sec, timereq.tv_nsec, 74 timerem.tv_sec, timerem.tv_nsec) < 0) { 75 tst_brkm(TBROK, NULL, "self_exec failed"); 76 } 77 #else 78 do_child(); 79 #endif 80 } 81 82 sleep(1); 83 84 /* Now send signal to child */ 85 SAFE_KILL(NULL, cpid, SIGINT); 86 87 /* Wait for child to execute */ 88 wait(&status); 89 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 90 tst_resm(TPASS, "nanosleep() failed, interrupted" 91 " by signal (%d) as expected", EINTR); 92 } else { 93 tst_resm(TFAIL, "child process exited abnormally; " 94 "status = %d", status); 95 } 96 } 97 98 tst_exit(); 99 } 100 101 static void do_child(void) 102 { 103 struct timespec timereq = {.tv_sec = 5, .tv_nsec = 9999}; 104 struct timespec timerem; 105 106 /* 107 * Call nanosleep() to suspend child process 108 * for specified time 'tv_sec'. 109 * Call should return before suspending execution 110 * for the specified time due to receipt of signal 111 * from Parent. 112 */ 113 TEST(nanosleep(&timereq, &timerem)); 114 115 if (TEST_RETURN == -1) { 116 117 /* Check for expected errno is set */ 118 if (TEST_ERRNO != EINTR) { 119 tst_resm(TFAIL | TTERRNO, 120 "nanosleep() failed; expected errno: %d", 121 EINTR); 122 exit(1); 123 } 124 } else { 125 tst_resm(TFAIL, "nanosleep() returns %ld, " 126 "expected -1, errno:%d", TEST_RETURN, EINTR); 127 exit(1); 128 } 129 130 exit(0); 131 } 132 133 static void setup(void) 134 { 135 tst_sig(FORK, DEF_HANDLER, NULL); 136 137 TEST_PAUSE; 138 139 if (signal(SIGINT, sig_handler) == SIG_ERR) { 140 tst_brkm(TBROK, NULL, 141 "signal() fails to setup signal handler"); 142 } 143 144 } 145 146 static void sig_handler(void) 147 { 148 } 149