Alien-uv
view release on metacpan or search on metacpan
libuv/src/win/process.c view on Meta::CPAN
/*
* Attempt to find the value of the PATH environment variable in the child's
* preprocessed environment.
*
* If found, a pointer into `env` is returned. If not found, NULL is returned.
*/
static WCHAR* find_path(WCHAR *env) {
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
if ((env[0] == L'P' || env[0] == L'p') &&
(env[1] == L'A' || env[1] == L'a') &&
(env[2] == L'T' || env[2] == L't') &&
(env[3] == L'H' || env[3] == L'h') &&
(env[4] == L'=')) {
return &env[5];
}
}
return NULL;
}
/*
* Called on Windows thread-pool thread to indicate that
* a child process has exited.
*/
static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
uv_process_t* process = (uv_process_t*) data;
uv_loop_t* loop = process->loop;
assert(didTimeout == FALSE);
assert(process);
assert(!process->exit_cb_pending);
process->exit_cb_pending = 1;
/* Post completed */
POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
}
/* Called on main thread after a child process has exited. */
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
int64_t exit_code;
DWORD status;
assert(handle->exit_cb_pending);
handle->exit_cb_pending = 0;
/* If we're closing, don't call the exit callback. Just schedule a close
* callback now. */
if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return;
}
/* Unregister from process notification. */
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(handle->wait_handle);
handle->wait_handle = INVALID_HANDLE_VALUE;
}
/* Set the handle to inactive: no callbacks will be made after the exit
* callback. */
uv__handle_stop(handle);
if (GetExitCodeProcess(handle->process_handle, &status)) {
exit_code = status;
} else {
/* Unable to obtain the exit code. This should never happen. */
exit_code = uv_translate_sys_error(GetLastError());
}
/* Fire the exit callback. */
if (handle->exit_cb) {
handle->exit_cb(handle, exit_code, handle->exit_signal);
}
}
void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_closing(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
/* This blocks until either the wait was cancelled, or the callback has
* completed. */
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
if (!r) {
/* This should never happen, and if it happens, we can't recover... */
uv_fatal_error(GetLastError(), "UnregisterWaitEx");
}
handle->wait_handle = INVALID_HANDLE_VALUE;
}
if (!handle->exit_cb_pending) {
uv_want_endgame(loop, (uv_handle_t*)handle);
}
}
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
assert(!handle->exit_cb_pending);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
/* Clean-up the process handle. */
CloseHandle(handle->process_handle);
uv__handle_close(handle);
}
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,
const uv_process_options_t* options) {
int i;
int err = 0;
WCHAR* path = NULL, *alloc_path = NULL;
BOOL result;
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
*env = NULL, *cwd = NULL;
STARTUPINFOW startup;
( run in 0.643 second using v1.01-cache-2.11-cpan-796a6f069b2 )