1 /* 2 * Check decoding of wait4 syscall. 3 * 4 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2017 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <assert.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <unistd.h> 36 #include <sys/wait.h> 37 #include <sys/resource.h> 38 39 static const char * 40 sprint_rusage(const struct rusage *const ru) 41 { 42 static char buf[1024]; 43 snprintf(buf, sizeof(buf), 44 "{ru_utime={tv_sec=%lld, tv_usec=%llu}" 45 ", ru_stime={tv_sec=%lld, tv_usec=%llu}" 46 #if VERBOSE 47 ", ru_maxrss=%lu" 48 ", ru_ixrss=%lu" 49 ", ru_idrss=%lu" 50 ", ru_isrss=%lu" 51 ", ru_minflt=%lu" 52 ", ru_majflt=%lu" 53 ", ru_nswap=%lu" 54 ", ru_inblock=%lu" 55 ", ru_oublock=%lu" 56 ", ru_msgsnd=%lu" 57 ", ru_msgrcv=%lu" 58 ", ru_nsignals=%lu" 59 ", ru_nvcsw=%lu" 60 ", ru_nivcsw=%lu}" 61 #else 62 ", ...}" 63 #endif 64 , (long long) ru->ru_utime.tv_sec 65 , zero_extend_signed_to_ull(ru->ru_utime.tv_usec) 66 , (long long) ru->ru_stime.tv_sec 67 , zero_extend_signed_to_ull(ru->ru_stime.tv_usec) 68 #if VERBOSE 69 , (long) ru->ru_maxrss 70 , (long) ru->ru_ixrss 71 , (long) ru->ru_idrss 72 , (long) ru->ru_isrss 73 , (long) ru->ru_minflt 74 , (long) ru->ru_majflt 75 , (long) ru->ru_nswap 76 , (long) ru->ru_inblock 77 , (long) ru->ru_oublock 78 , (long) ru->ru_msgsnd 79 , (long) ru->ru_msgrcv 80 , (long) ru->ru_nsignals 81 , (long) ru->ru_nvcsw 82 , (long) ru->ru_nivcsw 83 #endif 84 ); 85 return buf; 86 } 87 88 static pid_t 89 do_wait4(pid_t pid, int *wstatus, int options, struct rusage *ru) 90 { 91 sigset_t mask = {}; 92 sigaddset(&mask, SIGCHLD); 93 94 assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); 95 pid_t rc = wait4(pid, wstatus, options, ru); 96 assert(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0); 97 return rc; 98 } 99 100 int 101 main(void) 102 { 103 tprintf("%s", ""); 104 105 int fds[2]; 106 if (pipe(fds)) 107 perror_msg_and_fail("pipe"); 108 109 pid_t pid; 110 pid = fork(); 111 if (pid < 0) 112 perror_msg_and_fail("fork"); 113 114 if (!pid) { 115 char c; 116 (void) close(1); 117 assert(read(0, &c, sizeof(c)) == 1); 118 return 42; 119 } 120 121 (void) close(0); 122 123 TAIL_ALLOC_OBJECT_CONST_PTR(int, s); 124 if (wait4(pid, s, WNOHANG|__WALL, NULL)) 125 perror_msg_and_fail("wait4 #1"); 126 tprintf("wait4(%d, %p, WNOHANG|__WALL, NULL) = 0\n", pid, s); 127 128 TAIL_ALLOC_OBJECT_CONST_PTR(struct rusage, rusage); 129 if (wait4(pid, s, WNOHANG|__WALL, rusage)) 130 perror_msg_and_fail("wait4 #2"); 131 tprintf("wait4(%d, %p, WNOHANG|__WALL, %p) = 0\n", pid, s, rusage); 132 133 assert(write(1, "", 1) == 1); 134 (void) close(1); 135 136 assert(do_wait4(pid, s, 0, rusage) == pid); 137 assert(WIFEXITED(*s) && WEXITSTATUS(*s) == 42); 138 tprintf("wait4(%d, [{WIFEXITED(s) && WEXITSTATUS(s) == 42}], 0, %s)" 139 " = %d\n", pid, sprint_rusage(rusage), pid); 140 141 pid = fork(); 142 if (pid < 0) 143 perror_msg_and_fail("fork"); 144 145 if (!pid) { 146 (void) raise(SIGUSR1); 147 return 1; 148 } 149 150 assert(do_wait4(pid, s, __WALL, rusage) == pid); 151 assert(WIFSIGNALED(*s) && WTERMSIG(*s) == SIGUSR1); 152 tprintf("wait4(%d, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGUSR1}]" 153 ", __WALL, %s) = %d\n", pid, sprint_rusage(rusage), pid); 154 155 if (pipe(fds)) 156 perror_msg_and_fail("pipe"); 157 pid = fork(); 158 if (pid < 0) 159 perror_msg_and_fail("fork"); 160 161 if (!pid) { 162 (void) close(1); 163 raise(SIGSTOP); 164 char c; 165 assert(read(0, &c, sizeof(c)) == 1); 166 return 0; 167 } 168 169 (void) close(0); 170 171 assert(do_wait4(pid, s, WSTOPPED, rusage) == pid); 172 assert(WIFSTOPPED(*s) && WSTOPSIG(*s) == SIGSTOP); 173 tprintf("wait4(%d, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGSTOP}]" 174 ", WSTOPPED, %s) = %d\n", pid, sprint_rusage(rusage), pid); 175 176 if (kill(pid, SIGCONT)) 177 perror_msg_and_fail("kill(SIGCONT)"); 178 179 #if defined WCONTINUED && defined WIFCONTINUED 180 assert(do_wait4(pid, s, WCONTINUED, rusage) == pid); 181 assert(WIFCONTINUED(*s)); 182 tprintf("wait4(%d, [{WIFCONTINUED(s)}], WCONTINUED" 183 ", %s) = %d\n", pid, sprint_rusage(rusage), pid); 184 #endif /* WCONTINUED && WIFCONTINUED */ 185 186 assert(write(1, "", 1) == 1); 187 (void) close(1); 188 189 assert(do_wait4(pid, s, 0, rusage) == pid); 190 assert(WIFEXITED(*s) && WEXITSTATUS(*s) == 0); 191 tprintf("wait4(%d, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0" 192 ", %s) = %d\n", pid, sprint_rusage(rusage), pid); 193 194 assert(wait4(-1, s, WNOHANG|WSTOPPED|__WALL, rusage) == -1); 195 tprintf("wait4(-1, %p, WNOHANG|WSTOPPED|__WALL, %p) = -1 %s (%m)\n", 196 s, rusage, errno2name()); 197 198 tprintf("%s\n", "+++ exited with 0 +++"); 199 return 0; 200 } 201