1 /* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. 4 * All rights reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 #include <sys/wait.h> 9 10 #include <errno.h> 11 #include <pthread.h> 12 13 #include <syscall_utils.h> 14 15 #include <errno_private.h> 16 #include <syscalls.h> 17 #include <thread_defs.h> 18 19 20 pid_t 21 wait(int* _status) 22 { 23 return waitpid(-1, _status, 0); 24 } 25 26 extern "C" pid_t 27 _waitpid(pid_t pid, int* _status, int options, team_usage_info *usage_info) 28 { 29 // wait 30 siginfo_t info; 31 pid_t child = _kern_wait_for_child(pid, options | WEXITED, &info, 32 usage_info); 33 34 pthread_testcancel(); 35 36 if (child < 0) { 37 // When not getting a child status when WNOHANG was specified, don't 38 // fail. 39 if (child == B_WOULD_BLOCK && (options & WNOHANG) != 0) 40 return 0; 41 RETURN_AND_SET_ERRNO(child); 42 } 43 44 // prepare the status 45 if (_status != NULL) { 46 int status; 47 switch (info.si_code) { 48 case CLD_EXITED: 49 // fill in exit status for WIFEXITED() and WEXITSTATUS() 50 status = info.si_status & 0xff; 51 break; 52 53 case CLD_KILLED: 54 case CLD_DUMPED: 55 // fill in signal for WIFSIGNALED() and WTERMSIG() 56 status = (info.si_status << 8) & 0xff00; 57 // if core dumped, set flag for WIFCORED() 58 if (info.si_code == CLD_DUMPED) 59 status |= 0x10000; 60 break; 61 62 case CLD_CONTINUED: 63 // set flag for WIFCONTINUED() 64 status = 0x20000; 65 break; 66 67 case CLD_STOPPED: 68 // fill in signal for WIFSTOPPED() and WSTOPSIG() 69 status = (info.si_status << 16) & 0xff0000; 70 break; 71 72 case CLD_TRAPPED: 73 // we don't do that 74 default: 75 // should never get here -- assume exited 76 status = 0; 77 break; 78 } 79 80 *_status = status; 81 } 82 83 return child; 84 } 85 86 87 pid_t 88 waitpid(pid_t pid, int* _status, int options) 89 { 90 return _waitpid(pid, _status, options, NULL); 91 } 92 93 94 int 95 waitid(idtype_t idType, id_t id, siginfo_t* info, int options) 96 { 97 // translate the idType, id pair to a waitpid() style ID 98 switch (idType) { 99 case P_ALL: 100 // any child 101 id = -1; 102 break; 103 104 case P_PID: 105 // the child with the given ID 106 if (id <= 0) 107 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 108 break; 109 110 case P_PGID: 111 // any child in the given process group 112 if (id <= 1) 113 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 114 id = -id; 115 break; 116 117 default: 118 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 119 } 120 121 pid_t child = _kern_wait_for_child(id, options, info, NULL); 122 if (child >= 0 || child == B_WOULD_BLOCK) 123 return 0; 124 125 RETURN_AND_SET_ERRNO_TEST_CANCEL(child); 126 } 127