xref: /reactos/sdk/lib/ucrt/exec/wait.cpp (revision 04e0dc4a)
1 /***
2 *wait.c - wait for child process to terminate
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *       defines _wait() - wait for child process to terminate
8 *
9 *******************************************************************************/
10 
11 #include <corecrt_internal.h>
12 #include <errno.h>
13 #include <process.h>
14 #include <stdlib.h>
15 
16 /***
17 *int _cwait(stat_loc, process_id, action_code) - wait for specific child
18 *       process
19 *
20 *Purpose:
21 *       The function _cwait() suspends the calling-process until the specified
22 *       child-process terminates.  If the specifed child-process terminated
23 *       prior to the call to _cwait(), return is immediate.
24 *
25 *Entry:
26 *       int *stat_loc - pointer to where status is stored or nullptr
27 *       process_id - specific process id to be interrogated (0 means any)
28 *       action_code - specific action to perform on process ID
29 *                   either _WAIT_CHILD or _WAIT_GRANDCHILD
30 *
31 *Exit:
32 *       process ID of terminated child or -1 on error
33 *
34 *       *stat_loc is updated to contain the following:
35 *       Normal termination: lo-byte = 0, hi-byte = child exit code
36 *       Abnormal termination: lo-byte = term status, hi-byte = 0
37 *
38 *Exceptions:
39 *
40 *******************************************************************************/
41 
_cwait(int * const exit_code_result,intptr_t const process_id,int const action_code)42 extern "C" intptr_t __cdecl _cwait(
43     int*     const exit_code_result,
44     intptr_t const process_id,
45     int      const action_code
46     )
47 {
48     DBG_UNREFERENCED_PARAMETER(action_code);
49 
50     if (exit_code_result)
51         *exit_code_result = static_cast<DWORD>(-1);
52 
53     // Explicitly check for process ids -1 and -2.  In Windows NT, -1 is a handle
54     // to the current process and -2 is a handle to the current thread, and the
55     // OS will let you wait (forever) on either.
56     _VALIDATE_RETURN_NOEXC(process_id != -1 && process_id != -2, ECHILD, -1);
57 
58     __crt_unique_handle process_handle(reinterpret_cast<HANDLE>(process_id));
59 
60     // Wait for the child process and get its exit code:
61     DWORD exit_code;
62     if (WaitForSingleObject(process_handle.get(), static_cast<DWORD>(-1)) == 0 &&
63         GetExitCodeProcess(process_handle.get(), &exit_code))
64     {
65         if (exit_code_result)
66             *exit_code_result = exit_code;
67 
68         return process_id;
69     }
70 
71     // One of the API calls failed; map the error and return failure.
72     DWORD const os_error = GetLastError();
73     if (os_error == ERROR_INVALID_HANDLE)
74     {
75         errno = ECHILD;
76         _doserrno = os_error;
77     }
78     else
79     {
80         __acrt_errno_map_os_error(os_error);
81     }
82 
83     if (exit_code_result)
84         *exit_code_result = static_cast<DWORD>(-1);
85 
86     return -1;
87 }
88