Serenity Operating System
at master 90 lines 2.2 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <assert.h> 8#include <bits/pthread_cancel.h> 9#include <errno.h> 10#include <sys/wait.h> 11#include <syscall.h> 12#include <unistd.h> 13 14extern "C" { 15 16// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html 17pid_t wait(int* wstatus) 18{ 19 return waitpid(-1, wstatus, 0); 20} 21 22// https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html 23pid_t waitpid(pid_t waitee, int* wstatus, int options) 24{ 25 __pthread_maybe_cancel(); 26 27 siginfo_t siginfo; 28 idtype_t idtype; 29 id_t id; 30 31 if (waitee < -1) { 32 idtype = P_PGID; 33 id = -waitee; 34 } else if (waitee == -1) { 35 idtype = P_ALL; 36 id = 0; 37 } else if (waitee == 0) { 38 idtype = P_PGID; 39 id = getgid(); 40 } else { 41 idtype = P_PID; 42 id = waitee; 43 } 44 45 // To be able to detect if a child was found when WNOHANG is set, 46 // we need to clear si_pid, which will only be set if it was found. 47 siginfo.si_pid = 0; 48 int rc = waitid(idtype, id, &siginfo, options | WEXITED); 49 50 if (rc < 0) 51 return rc; 52 53 if ((options & WNOHANG) && siginfo.si_pid == 0) { 54 // No child in a waitable state was found. All other fields 55 // in siginfo are undefined 56 return 0; 57 } 58 59 if (wstatus) { 60 switch (siginfo.si_code) { 61 case CLD_EXITED: 62 *wstatus = siginfo.si_status << 8; 63 break; 64 case CLD_KILLED: 65 *wstatus = siginfo.si_status; 66 break; 67 case CLD_STOPPED: 68 *wstatus = siginfo.si_status << 8 | 0x7f; 69 break; 70 case CLD_CONTINUED: 71 *wstatus = 0xffff; 72 break; 73 default: 74 VERIFY_NOT_REACHED(); 75 } 76 } 77 78 return siginfo.si_pid; 79} 80 81// https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html 82int waitid(idtype_t idtype, id_t id, siginfo_t* infop, int options) 83{ 84 __pthread_maybe_cancel(); 85 86 Syscall::SC_waitid_params params { idtype, id, infop, options }; 87 int rc = syscall(SC_waitid, &params); 88 __RETURN_WITH_ERRNO(rc, rc, -1); 89} 90}