1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. 16 * 17 * History 18 * 07/2001 John George 19 * -Ported 20 * 04/2002 wjhuie sigset cleanups 21 */ 22 23 /* 24 * case 0: 25 * waitpid(pid, WNOHANG) should return 0 if there is a running child 26 * case 1: 27 * waitpid(pid, WNOHANG) should return the pid of the child if 28 * the child has exited 29 * case 2: 30 * waitpid(-1, 0) should return -1 with ECHILD if 31 * there are no children to wait for. 32 * case 3: 33 * waitpid(-1, WNOHANG) should return -1 with ECHILD if 34 * there are no children to wait for. 35 */ 36 37 #define _GNU_SOURCE 1 38 #include <sys/types.h> 39 #include <signal.h> 40 #include <errno.h> 41 #include <sys/wait.h> 42 #include <stdlib.h> 43 #include "tst_test.h" 44 45 static void cleanup_pid(pid_t pid) 46 { 47 if (pid > 0) { 48 kill(pid, SIGKILL); 49 waitpid(pid, NULL, 0); 50 } 51 } 52 53 static void case0(void) 54 { 55 pid_t pid, ret; 56 int status; 57 58 pid = SAFE_FORK(); 59 if (pid == 0) { 60 TST_CHECKPOINT_WAIT(0); 61 62 exit(0); 63 } 64 65 for (;;) { 66 ret = waitpid(pid, &status, WNOHANG); 67 68 if ((ret == -1) && (errno == EINTR)) 69 continue; 70 71 if (ret == 0) 72 break; 73 74 tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected 0", 75 ret); 76 cleanup_pid(pid); 77 return; 78 } 79 80 TST_CHECKPOINT_WAKE(0); 81 SAFE_WAITPID(pid, NULL, 0); 82 83 tst_res(TPASS, "waitpid(pid, WNOHANG) = 0 for a running child"); 84 } 85 86 static void case1(void) 87 { 88 pid_t pid, ret; 89 int status; 90 91 pid = SAFE_FORK(); 92 if (pid == 0) 93 exit(0); 94 95 for (;;) { 96 ret = waitpid(pid, &status, WNOHANG); 97 98 if ((ret == -1) && (errno == EINTR)) 99 continue; 100 if (ret == 0) 101 continue; 102 103 if (ret == pid) 104 break; 105 106 tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected %d", 107 ret, pid); 108 cleanup_pid(pid); 109 return; 110 } 111 112 if (!WIFEXITED(status)) { 113 tst_res(TFAIL, "Child exited abnormally"); 114 return; 115 } 116 117 if (WEXITSTATUS(status) != 0) { 118 tst_res(TFAIL, "Child exited with %d, expected 0", 119 WEXITSTATUS(status)); 120 return; 121 } 122 123 tst_res(TPASS, "waitpid(pid, WNOHANG) = pid for an exited child"); 124 } 125 126 static void case2(void) 127 { 128 pid_t ret; 129 int status; 130 131 ret = waitpid(-1, &status, 0); 132 133 if (ret != -1) { 134 tst_res(TFAIL, "Expected -1, got %d", ret); 135 return; 136 } 137 if (errno != ECHILD) { 138 tst_res(TFAIL, "Expected %s, got %s", 139 tst_strerrno(ECHILD), tst_strerrno(errno)); 140 return; 141 } 142 143 tst_res(TPASS, "waitpid(-1, 0) = -1 with ECHILD if no children"); 144 } 145 146 static void case3(void) 147 { 148 pid_t ret; 149 int status; 150 151 ret = waitpid(-1, &status, WNOHANG); 152 if (ret != -1) { 153 tst_res(TFAIL, "WNOHANG: Expected -1, got %d", ret); 154 return; 155 } 156 if (errno != ECHILD) { 157 tst_res(TFAIL, "WNOHANG: Expected %s, got %s", 158 tst_strerrno(ECHILD), tst_strerrno(errno)); 159 return; 160 } 161 162 tst_res(TPASS, "waitpid(-1, WNOHANG) = -1 with ECHILD if no children"); 163 } 164 165 static void (*tests[])(void) = { case0, case1, case2, case3 }; 166 167 static void waitpid09_test(unsigned int id) 168 { 169 tests[id](); 170 } 171 172 static struct tst_test test = { 173 .forks_child = 1, 174 .needs_checkpoints = 1, 175 .test = waitpid09_test, 176 .tcnt = ARRAY_SIZE(tests), 177 }; 178