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, &info, usage_info); 32 33 pthread_testcancel(); 34 35 if (child < 0) { 36 // When not getting a child status when WNOHANG was specified, don't 37 // fail. 38 if (child == B_WOULD_BLOCK && (options & WNOHANG) != 0) 39 return 0; 40 RETURN_AND_SET_ERRNO(child); 41 } 42 43 // prepare the status 44 if (_status != NULL) { 45 int status; 46 switch (info.si_code) { 47 case CLD_EXITED: 48 // fill in exit status for WIFEXITED() and WEXITSTATUS() 49 status = info.si_status & 0xff; 50 break; 51 52 case CLD_KILLED: 53 case CLD_DUMPED: 54 // fill in signal for WIFSIGNALED() and WTERMSIG() 55 status = (info.si_status << 8) & 0xff00; 56 // if core dumped, set flag for WIFCORED() 57 if (info.si_code == CLD_DUMPED) 58 status |= 0x10000; 59 break; 60 61 case CLD_CONTINUED: 62 // set flag for WIFCONTINUED() 63 status = 0x20000; 64 break; 65 66 case CLD_STOPPED: 67 // fill in signal for WIFSTOPPED() and WSTOPSIG() 68 status = (info.si_status << 16) & 0xff0000; 69 break; 70 71 case CLD_TRAPPED: 72 // we don't do that 73 default: 74 // should never get here -- assume exited 75 status = 0; 76 break; 77 } 78 79 *_status = status; 80 } 81 82 return child; 83 } 84 85 86 pid_t 87 waitpid(pid_t pid, int* _status, int options) 88 { 89 return _waitpid(pid, _status, options, NULL); 90 } 91 92 93 int 94 waitid(idtype_t idType, id_t id, siginfo_t* info, int options) 95 { 96 // translate the idType, id pair to a waitpid() style ID 97 switch (idType) { 98 case P_ALL: 99 // any child 100 id = -1; 101 break; 102 103 case P_PID: 104 // the child with the given ID 105 if (id <= 0) 106 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 107 break; 108 109 case P_PGID: 110 // any child in the given process group 111 if (id <= 1) 112 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 113 id = -id; 114 break; 115 116 default: 117 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 118 } 119 120 pid_t child = _kern_wait_for_child(id, options, info, NULL); 121 if (child >= 0 || child == B_WOULD_BLOCK) 122 return 0; 123 124 RETURN_AND_SET_ERRNO_TEST_CANCEL(child); 125 } 126