void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, uv_write_t* req) { assert(handle->type == UV_TCP); assert(handle->write_queue_size >= req->queued_bytes); handle->write_queue_size -= req->queued_bytes; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); } if (req->event_handle) { CloseHandle(req->event_handle); } } if (req->cb) { uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req)); ((uv_write_cb)req->cb)(req, loop->last_err.code == UV_OK ? 0 : -1); } handle->write_reqs_pending--; if (handle->flags & UV_HANDLE_SHUTTING && handle->write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } DECREASE_PENDING_REQ_COUNT(handle); uv_unref(loop); }
//******************************************************************************************** // Function: CleanupDrt // // Description: Deletes and Frees the various objects and providers used by the DRT // //******************************************************************************************** void CleanupDrt(DRT_CONTEXT *Drt) { for(UINT i=0; i<Drt->registrations.size(); i++) { DrtUnregisterKey(Drt->registrations[i].hDrtReg); if(Drt->registrations[i].regInfo.key.pb) free(Drt->registrations[i].regInfo.key.pb); if(Drt->registrations[i].regInfo.appData.pb) free(Drt->registrations[i].regInfo.appData.pb); } Drt->registrations.clear(); if (Drt->DrtWaitEvent != NULL) { UnregisterWait(Drt->DrtWaitEvent); } if (Drt->hDrt != NULL) { DrtClose(Drt->hDrt); Drt->hDrt = NULL; } if (Drt->eventHandle!= NULL) { CloseHandle(Drt->eventHandle); Drt->eventHandle = NULL; } if (Drt->settings.pBootstrapProvider != NULL) { if(Drt->BootstrapProviderType == 0) DrtDeleteDnsBootstrapResolver(Drt->settings.pBootstrapProvider); else if(Drt->BootstrapProviderType == 1) DrtDeletePnrpBootstrapResolver(Drt->settings.pBootstrapProvider); else if(Drt->BootstrapProviderType == 2) DrtDeleteCustomBootstrapResolver(Drt->settings.pBootstrapProvider); } if (Drt->settings.pSecurityProvider != NULL) { if(Drt->SecurityProviderType == 0) DrtDeleteNullSecurityProvider(Drt->settings.pSecurityProvider); else if(Drt->SecurityProviderType == 1) DrtDeleteDerivedKeySecurityProvider(Drt->settings.pSecurityProvider); else if(Drt->SecurityProviderType == 2) DrtDeleteCustomSecurityProvider(Drt->settings.pSecurityProvider); } if (Drt->pRoot != NULL) { CertFreeCertificateContext(Drt->pRoot); } if (Drt->pLocal != NULL) { CertFreeCertificateContext(Drt->pLocal); } }
/* Called on main thread after a child process has exited. */ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { DWORD exit_code; /* Unregister from process notification. */ if (handle->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->wait_handle); handle->wait_handle = INVALID_HANDLE_VALUE; } if (handle->process_handle != INVALID_HANDLE_VALUE) { /* Get the exit code. */ if (!GetExitCodeProcess(handle->process_handle, &exit_code)) { exit_code = 127; } /* Clean-up the process handle. */ CloseHandle(handle->process_handle); handle->process_handle = INVALID_HANDLE_VALUE; } else { /* We probably left the child stdio handles open to report the error */ /* asynchronously, so close them now. */ close_child_stdio(handle); /* The process never even started in the first place. */ exit_code = 127; } /* Fire the exit callback. */ if (handle->exit_cb) { handle->exit_cb(handle, exit_code, handle->exit_signal); } }
void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, uv_write_t* req) { int err; assert(handle->type == UV_TCP); assert(handle->write_queue_size >= req->queued_bytes); handle->write_queue_size -= req->queued_bytes; UNREGISTER_HANDLE_REQ(loop, handle, req); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } if (req->cb) { err = GET_REQ_SOCK_ERROR(req); req->cb(req, uv_translate_sys_error(err)); } handle->write_reqs_pending--; if (handle->shutdown_req != NULL && handle->write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } DECREASE_PENDING_REQ_COUNT(handle); }
static void CALLBACK trigger_process_detection( void* lpParameter, BOOLEAN TimerOrWaitFired ) { opal_process_handle_t* handle = (opal_process_handle_t*)lpParameter; DWORD exitCode; opal_list_remove_item( ®istered_cb, (opal_list_item_t*)handle ); /** * As this item will never be triggered again, we can safely remove the * registered handle. */ if( 0 == UnregisterWait( handle->registered_handle ) ) { /** * If any callback functions associated with the timer have not completed when * UnregisterWait is called, UnregisterWait unregisters the wait on the callback * functions and fails with the ERROR_IO_PENDING error code. The error code does * not indicate that the function has failed, and the function does not need to * be called again. If your code requires an error code to set only when the * unregister operation has failed, call UnregisterWaitEx instead. */ int error = GetLastError(); } handle->registered_handle = INVALID_HANDLE_VALUE; /** * Get the exit code of the process. */ if( 0 == GetExitCodeProcess( (HANDLE)handle->pid, &exitCode ) ) { int error = GetLastError(); } handle->status = (int)exitCode; handle->callback(handle->pid, handle->status, handle->data); OBJ_RELEASE( handle ); }
static void CALLBACK try_wait_callback( void * data, BOOLEAN is_timeout ) { struct _cmdtab_t * slot = ( struct _cmdtab_t * )data; WaitForSingleObject( process_queue.write_okay, INFINITE ); process_queue.job_index = slot - cmdtab; assert( !is_timeout ); SetEvent( process_queue.read_okay ); /* Okay. Non-blocking. */ UnregisterWait( slot->wait_handle ); }
void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, uv_write_t* req) { assert(handle->type == UV_NAMED_PIPE); assert(handle->write_queue_size >= req->queued_bytes); handle->write_queue_size -= req->queued_bytes; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } if (req->ipc_header) { if (req == &handle->ipc_header_write_req) { req->type = UV_UNKNOWN_REQ; } else { free(req); } } else { if (req->cb) { if (!REQ_SUCCESS(req)) { uv__set_sys_error(loop, GET_REQ_ERROR(req)); ((uv_write_cb)req->cb)(req, -1); } else { ((uv_write_cb)req->cb)(req, 0); } } } handle->write_reqs_pending--; if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE && handle->non_overlapped_writes_tail) { assert(handle->write_reqs_pending > 0); uv_queue_non_overlapped_write(handle); } if (handle->write_reqs_pending == 0) { uv_unref(loop); } if (handle->write_reqs_pending == 0 && handle->flags & UV_HANDLE_SHUTTING) { uv_want_endgame(loop, (uv_handle_t*)handle); } DECREASE_PENDING_REQ_COUNT(handle); }
VOID CALLBACK WindowsOpAutoUpdatePI::PackageExtractor::WaitOrTimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) { g_thread_tools->PostMessageToMainThread(MSG_AUTOUPDATE_UNPACKING_COMPLETE, (MH_PARAM_1)lpParameter, NULL); PackageExtractor* pkg_ext = (PackageExtractor*)lpParameter; UnregisterWait(pkg_ext->m_wait_object); CloseHandle(pkg_ext->m_process_handle); delete pkg_ext; }
static void opal_process_handle_destruct( opal_object_t* obj ) { opal_process_handle_t* handle = (opal_process_handle_t*)obj; if( INVALID_HANDLE_VALUE != handle->registered_handle ) { if( 0 == UnregisterWait( handle->registered_handle ) ) { int error = GetLastError(); } if( 0 == CloseHandle( handle->registered_handle ) ) { int error = GetLastError(); } handle->registered_handle = INVALID_HANDLE_VALUE; } }
static PyObject * overlapped_UnregisterWait(PyObject *self, PyObject *args) { HANDLE WaitHandle; BOOL ret; if (!PyArg_ParseTuple(args, F_HANDLE, &WaitHandle)) return NULL; Py_BEGIN_ALLOW_THREADS ret = UnregisterWait(WaitHandle); Py_END_ALLOW_THREADS if (!ret) return SetFromWindowsErr(0); Py_RETURN_NONE; }
static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) { uv_loop_t* loop; uv_tty_t* handle; uv_req_t* req; assert(data); assert(!didTimeout); req = (uv_req_t*) data; handle = (uv_tty_t*) req->data; loop = handle->loop; UnregisterWait(handle->read_raw_wait); handle->read_raw_wait = NULL; SET_REQ_SUCCESS(req); POST_COMPLETION_FOR_REQ(loop, req); }
static VOID CALLBACK pthreads_win32_unnotice(void* parameter, BOOLEAN timerOrWait) { pthread_t pth = parameter; pthread_t self = tls_impersonate(pth); tls_call_destructors(); CloseHandle(pth->handle); /* if (pth->fiber && pth->own_fiber) { DeleteFiber(pth->fiber); } */ UnregisterWait(pth->wait_handle); tls_impersonate(self); pthread_mutex_destroy(&pth->fiber_lock); pthread_mutex_destroy(&pth->lock); free(pth); }
Bool Instance::Unload() { // free wait handle if( _wait_handle ) UnregisterWait(_wait_handle); // unload injected dll _injector.Unload(); // close process handle if( _process ) CloseHandle(_process); // reset _process_id = 0; _process = NULL; _wait_handle = NULL; return true; }
void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, uv_write_t* req) { int err; assert(handle->type == UV_TCP); assert(handle->write_queue_size >= req->u.io.queued_bytes); handle->write_queue_size -= req->u.io.queued_bytes; UNREGISTER_HANDLE_REQ(loop, handle, req); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } if (req->cb) { err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req)); if (err == UV_ECONNABORTED) { /* use UV_ECANCELED for consistency with Unix */ err = UV_ECANCELED; } req->cb(req, err); } handle->stream.conn.write_reqs_pending--; if (handle->stream.conn.shutdown_req != NULL && handle->stream.conn.write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } DECREASE_PENDING_REQ_COUNT(handle); }
/* Called on main thread after a child process has exited. */ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { DWORD exit_code; 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) { #ifndef WINONECORE UnregisterWait(handle->wait_handle); #endif 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 (handle->spawn_error.code != UV_OK) { /* Spawning failed. */ exit_code = (DWORD) - 1; } else if (!GetExitCodeProcess(handle->process_handle, &exit_code)) { /* Unable to to obtain the exit code. This should never happen. */ exit_code = (DWORD) - 1; } /* Fire the exit callback. */ if (handle->exit_cb) { loop->last_err = handle->spawn_error; handle->exit_cb(handle, exit_code, handle->exit_signal); } }
int __pmSetSignalHandler(int sig, __pmSignalHandler func) { int sts, index; char *signame, evname[64]; HANDLE eventhdl, waithdl; if ((signame = MapSignals(sig, &index)) < 0) return index; if (signals[index].callback) { /* remove old handler */ UnregisterWait(signals[index].waithandle); CloseHandle(signals[index].eventhandle); signals[index].callback = NULL; signals[index].signal = -1; } if (func == SIG_IGN) return 0; sts = 0; snprintf(evname, sizeof(evname), "PCP/%" FMT_PID "/%s", getpid(), signame); if (!(eventhdl = CreateEvent(NULL, FALSE, FALSE, TEXT(evname)))) { sts = GetLastError(); fprintf(stderr, "CreateEvent::%s failed (%d)\n", signame, sts); } else if (!RegisterWaitForSingleObject(&waithdl, eventhdl, SignalCallback, (PVOID)index, INFINITE, 0)) { sts = GetLastError(); fprintf(stderr, "RegisterWait::%s failed (%d)\n", signame, sts); } else { signals[index].eventhandle = eventhdl; signals[index].waithandle = waithdl; signals[index].callback = func; signals[index].signal = sig; } return sts; }
/* Called on main thread after a child process has exited. */ void uv_process_proc_exit(uv_process_t* handle) { int i; DWORD exit_code; /* Close stdio handles. */ for (i = 0; i < COUNTOF(handle->stdio_pipes); i++) { if (handle->stdio_pipes[i].child_pipe != INVALID_HANDLE_VALUE) { CloseHandle(handle->stdio_pipes[i].child_pipe); handle->stdio_pipes[i].child_pipe = INVALID_HANDLE_VALUE; } } /* Unregister from process notification. */ if (handle->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->wait_handle); handle->wait_handle = INVALID_HANDLE_VALUE; } if (handle->process_handle != INVALID_HANDLE_VALUE) { /* Get the exit code. */ if (!GetExitCodeProcess(handle->process_handle, &exit_code)) { exit_code = 127; } /* Clean-up the process handle. */ CloseHandle(handle->process_handle); handle->process_handle = INVALID_HANDLE_VALUE; } else { /* The process never even started in the first place. */ exit_code = 127; } /* Fire the exit callback. */ if (handle->exit_cb) { handle->exit_cb(handle, exit_code, handle->exit_signal); } }
/* 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 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_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { int status; int sys_error; unsigned int i; uv_tcp_accept_t* req; if (handle->flags & UV_HANDLE_CONNECTION && handle->flags & UV_HANDLE_SHUTTING && !(handle->flags & UV_HANDLE_SHUT) && handle->write_reqs_pending == 0) { if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) { status = 0; handle->flags |= UV_HANDLE_SHUT; } else { status = -1; sys_error = WSAGetLastError(); } if (handle->shutdown_req->cb) { if (status == -1) { uv__set_sys_error(loop, sys_error); } handle->shutdown_req->cb(handle->shutdown_req, status); } DECREASE_PENDING_REQ_COUNT(handle); return; } if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) { for (i = 0; i < uv_simultaneous_server_accepts; i++) { req = &handle->accept_reqs[i]; if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } } free(handle->accept_reqs); handle->accept_reqs = NULL; } if (handle->close_cb) { handle->close_cb((uv_handle_t*)handle); } active_tcp_streams--; uv_unref(loop); } }
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { int status; unsigned int i; uv_tcp_accept_t* req; if (handle->flags & UV_HANDLE_CONNECTION && handle->shutdown_req != NULL && handle->write_reqs_pending == 0) { UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); if (handle->flags & UV__HANDLE_CLOSING) { status = -1; uv__set_artificial_error(loop, UV_ECANCELED); } else if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) { status = 0; } else { status = -1; uv__set_sys_error(loop, WSAGetLastError()); } if (handle->shutdown_req->cb) { handle->shutdown_req->cb(handle->shutdown_req, status); } handle->shutdown_req = NULL; DECREASE_PENDING_REQ_COUNT(handle); return; } if (handle->flags & UV__HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) { closesocket(handle->socket); handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; } if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) { for (i = 0; i < uv_simultaneous_server_accepts; i++) { req = &handle->accept_reqs[i]; if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } } free(handle->accept_reqs); handle->accept_reqs = NULL; } if (handle->flags & UV_HANDLE_CONNECTION && handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } if (handle->read_req.event_handle) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } } uv__handle_close(handle); loop->active_tcp_streams--; } }
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { unsigned int uv_alloced; DWORD result; uv_shutdown_t* req; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_PIPE_LOCAL_INFORMATION pipe_info; if (handle->flags & UV_HANDLE_SHUTTING && !(handle->flags & UV_HANDLE_SHUT) && handle->write_reqs_pending == 0) { req = handle->shutdown_req; /* Try to avoid flushing the pipe buffer in the thread pool. */ nt_status = pNtQueryInformationFile(handle->handle, &io_status, &pipe_info, sizeof pipe_info, FilePipeLocalInformation); if (nt_status != STATUS_SUCCESS) { /* Failure */ handle->flags &= ~UV_HANDLE_SHUTTING; if (req->cb) { uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status)); req->cb(req, -1); } DECREASE_PENDING_REQ_COUNT(handle); return; } if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { handle->flags |= UV_HANDLE_SHUT; /* Short-circuit, no need to call FlushFileBuffers. */ uv_insert_pending_req(loop, (uv_req_t*) req); return; } /* Run FlushFileBuffers in the thread pool. */ result = QueueUserWorkItem(pipe_shutdown_thread_proc, req, WT_EXECUTELONGFUNCTION); if (result) { /* Mark the handle as shut now to avoid going through this again. */ handle->flags |= UV_HANDLE_SHUT; return; } else { /* Failure. */ handle->flags &= ~UV_HANDLE_SHUTTING; if (req->cb) { uv__set_sys_error(loop, GetLastError()); req->cb(req, -1); } DECREASE_PENDING_REQ_COUNT(handle); return; } } if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; if (handle->flags & UV_HANDLE_CONNECTION) { if (handle->pending_socket_info) { free(handle->pending_socket_info); handle->pending_socket_info = NULL; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } if (handle->read_req.event_handle) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } } } if (handle->flags & UV_HANDLE_PIPESERVER) { assert(handle->accept_reqs); free(handle->accept_reqs); handle->accept_reqs = NULL; } /* Remember the state of this flag because the close callback is */ /* allowed to clobber or free the handle's memory */ uv_alloced = handle->flags & UV_HANDLE_UV_ALLOCED; if (handle->close_cb) { handle->close_cb((uv_handle_t*)handle); } if (uv_alloced) { free(handle); } uv_unref(loop); } }
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { DWORD result; uv_shutdown_t* req; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_PIPE_LOCAL_INFORMATION pipe_info; if ((handle->flags & UV_HANDLE_CONNECTION) && handle->shutdown_req != NULL && handle->write_reqs_pending == 0) { req = handle->shutdown_req; /* Clear the shutdown_req field so we don't go here again. */ handle->shutdown_req = NULL; if (handle->flags & UV__HANDLE_CLOSING) { UNREGISTER_HANDLE_REQ(loop, handle, req); /* Already closing. Cancel the shutdown. */ if (req->cb) { uv__set_artificial_error(loop, UV_ECANCELED); req->cb(req, -1); } DECREASE_PENDING_REQ_COUNT(handle); return; } /* Try to avoid flushing the pipe buffer in the thread pool. */ nt_status = pNtQueryInformationFile(handle->handle, &io_status, &pipe_info, sizeof pipe_info, FilePipeLocalInformation); if (nt_status != STATUS_SUCCESS) { /* Failure */ UNREGISTER_HANDLE_REQ(loop, handle, req); handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ if (req->cb) { uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status)); req->cb(req, -1); } DECREASE_PENDING_REQ_COUNT(handle); return; } if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { /* Short-circuit, no need to call FlushFileBuffers. */ uv_insert_pending_req(loop, (uv_req_t*) req); return; } /* Run FlushFileBuffers in the thread pool. */ result = QueueUserWorkItem(pipe_shutdown_thread_proc, req, WT_EXECUTELONGFUNCTION); if (result) { return; } else { /* Failure. */ UNREGISTER_HANDLE_REQ(loop, handle, req); handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ if (req->cb) { uv__set_sys_error(loop, GetLastError()); req->cb(req, -1); } DECREASE_PENDING_REQ_COUNT(handle); return; } } if (handle->flags & UV__HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (handle->flags & UV_HANDLE_CONNECTION) { if (handle->pending_ipc_info.socket_info) { free(handle->pending_ipc_info.socket_info); handle->pending_ipc_info.socket_info = NULL; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } if (handle->read_req.event_handle) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } } } if (handle->flags & UV_HANDLE_PIPESERVER) { assert(handle->accept_reqs); free(handle->accept_reqs); handle->accept_reqs = NULL; } uv__handle_close(handle); } }
int uv_spawn(uv_loop_t* loop, uv_process_t* process, uv_process_options_t options) { int err = 0, keep_child_stdio_open = 0; wchar_t* path = NULL; int size; BOOL result; wchar_t* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL; HANDLE* child_stdio = process->child_stdio; STARTUPINFOW startup; PROCESS_INFORMATION info; if (!options.file) { uv__set_artificial_error(loop, UV_EINVAL); return -1; } uv_process_init(loop, process); process->exit_cb = options.exit_cb; UTF8_TO_UTF16(options.file, application); arguments = options.args ? make_program_args(options.args, options.windows_verbatim_arguments) : NULL; env = options.env ? make_program_env(options.env) : NULL; if (options.cwd) { UTF8_TO_UTF16(options.cwd, cwd); } else { size = GetCurrentDirectoryW(0, NULL) * sizeof(wchar_t); if (size) { cwd = (wchar_t*)malloc(size); if (!cwd) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } GetCurrentDirectoryW(size, cwd); } else { uv__set_sys_error(loop, GetLastError()); err = -1; goto done; } } /* Get PATH env. variable. */ size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1; path = (wchar_t*)malloc(size * sizeof(wchar_t)); if (!path) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } GetEnvironmentVariableW(L"PATH", path, size * sizeof(wchar_t)); path[size - 1] = L'\0'; application_path = search_path(application, cwd, path); if (!application_path) { /* CreateProcess will fail, but this allows us to pass this error to */ /* the user asynchronously. */ application_path = application; } /* Create stdio pipes. */ if (options.stdin_stream) { if (options.stdin_stream->ipc) { err = uv_create_stdio_pipe_pair( loop, options.stdin_stream, &child_stdio[0], PIPE_ACCESS_DUPLEX, GENERIC_READ | FILE_WRITE_ATTRIBUTES | GENERIC_WRITE, 1); } else { err = uv_create_stdio_pipe_pair( loop, options.stdin_stream, &child_stdio[0], PIPE_ACCESS_OUTBOUND, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0); } } else { err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]); } if (err) { goto done; } if (options.stdout_stream) { err = uv_create_stdio_pipe_pair( loop, options.stdout_stream, &child_stdio[1], PIPE_ACCESS_INBOUND, GENERIC_WRITE, 0); } else { err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]); } if (err) { goto done; } if (options.stderr_stream) { err = uv_create_stdio_pipe_pair( loop, options.stderr_stream, &child_stdio[2], PIPE_ACCESS_INBOUND, GENERIC_WRITE, 0); } else { err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]); } if (err) { goto done; } startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES; startup.cbReserved2 = 0; startup.lpReserved2 = NULL; startup.hStdInput = child_stdio[0]; startup.hStdOutput = child_stdio[1]; startup.hStdError = child_stdio[2]; if (CreateProcessW(application_path, arguments, NULL, NULL, 1, CREATE_UNICODE_ENVIRONMENT, env, cwd, &startup, &info)) { /* Spawn succeeded */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; if (options.stdin_stream && options.stdin_stream->ipc) { options.stdin_stream->ipc_pid = info.dwProcessId; } /* Setup notifications for when the child process exits. */ result = RegisterWaitForSingleObject(&process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!result) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); } else { /* CreateProcessW failed, but this failure should be delivered */ /* asynchronously to retain unix compatibility. So pretent spawn */ /* succeeded, and start a thread instead that prints an error */ /* to the child's intended stderr. */ process->spawn_errno = GetLastError(); keep_child_stdio_open = 1; if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) { uv_fatal_error(GetLastError(), "QueueUserWorkItem"); } } done: free(application); if (application_path != application) { free(application_path); } free(arguments); free(cwd); free(env); free(path); /* Under normal circumstances we should close the stdio handles now - */ /* the child now has its own duplicates, or something went horribly wrong. */ /* The only exception is when CreateProcess has failed, then we actually */ /* need to keep the stdio handles to report the error asynchronously. */ if (!keep_child_stdio_open) { close_child_stdio(process); } else { /* We're keeping the handles open, the thread pool is going to have */ /* it's way with them. But at least make them noninheritable. */ int i; for (i = 0; i < COUNTOF(process->child_stdio); i++) { SetHandleInformation(child_stdio[i], HANDLE_FLAG_INHERIT, 0); } } if (err) { if (process->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(process->wait_handle); process->wait_handle = INVALID_HANDLE_VALUE; } if (process->process_handle != INVALID_HANDLE_VALUE) { CloseHandle(process->process_handle); process->process_handle = INVALID_HANDLE_VALUE; } } return err; }
int uv_spawn(uv_process_t* process, uv_process_options_t options) { int err = 0, i; wchar_t* path; int size; wchar_t* application_path, *application, *arguments, *env, *cwd; STARTUPINFOW startup; PROCESS_INFORMATION info; uv_process_init(process); process->exit_cb = options.exit_cb; UTF8_TO_UTF16(options.file, application); arguments = options.args ? make_program_args(options.args, options.windows_verbatim_arguments) : NULL; env = options.env ? make_program_env(options.env) : NULL; if (options.cwd) { UTF8_TO_UTF16(options.cwd, cwd); } else { size = GetCurrentDirectoryW(0, NULL) * sizeof(wchar_t); if (size) { cwd = (wchar_t*)malloc(size); if (!cwd) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } GetCurrentDirectoryW(size, cwd); } else { uv_set_sys_error(GetLastError()); err = -1; goto done; } } /* Get PATH env. variable. */ size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1; path = (wchar_t*)malloc(size * sizeof(wchar_t)); if (!path) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } GetEnvironmentVariableW(L"PATH", path, size * sizeof(wchar_t)); path[size - 1] = L'\0'; application_path = search_path(application, cwd, path, DEFAULT_PATH_EXT); if (!application_path) { /* CreateProcess will fail, but this allows us to pass this error to */ /* the user asynchronously. */ application_path = application; } /* Create stdio pipes. */ if (options.stdin_stream) { err = uv_create_stdio_pipe_pair(options.stdin_stream, &process->stdio_pipes[0].child_pipe, PIPE_ACCESS_OUTBOUND, GENERIC_READ | FILE_WRITE_ATTRIBUTES); if (err) { goto done; } process->stdio_pipes[0].server_pipe = options.stdin_stream; } if (options.stdout_stream) { err = uv_create_stdio_pipe_pair(options.stdout_stream, &process->stdio_pipes[1].child_pipe, PIPE_ACCESS_INBOUND, GENERIC_WRITE); if (err) { goto done; } process->stdio_pipes[1].server_pipe = options.stdout_stream; } if (options.stderr_stream) { err = uv_create_stdio_pipe_pair(options.stderr_stream, &process->stdio_pipes[2].child_pipe, PIPE_ACCESS_INBOUND, GENERIC_WRITE); if (err) { goto done; } process->stdio_pipes[2].server_pipe = options.stderr_stream; } startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES; startup.cbReserved2 = 0; startup.lpReserved2 = NULL; startup.hStdInput = process->stdio_pipes[0].child_pipe; startup.hStdOutput = process->stdio_pipes[1].child_pipe; startup.hStdError = process->stdio_pipes[2].child_pipe; if (CreateProcessW(application_path, arguments, NULL, NULL, 1, CREATE_UNICODE_ENVIRONMENT, env, cwd, &startup, &info)) { /* Spawn succeeded */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; /* Setup notifications for when the child process exits. */ if (!RegisterWaitForSingleObject(&process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); } else { /* CreateProcessW failed, but this failure should be delivered */ /* asynchronously to retain unix compatibility. So pretent spawn */ /* succeeded, and start a thread instead that prints an error */ /* to the child's intended stderr. */ process->spawn_errno = GetLastError(); if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) { uv_fatal_error(GetLastError(), "QueueUserWorkItem"); } } done: free(application); if (application_path != application) { free(application_path); } free(arguments); free(cwd); free(env); free(path); if (err) { for (i = 0; i < COUNTOF(process->stdio_pipes); i++) { if (process->stdio_pipes[i].child_pipe != INVALID_HANDLE_VALUE) { CloseHandle(process->stdio_pipes[i].child_pipe); process->stdio_pipes[i].child_pipe = INVALID_HANDLE_VALUE; } } if (process->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(process->wait_handle); process->wait_handle = INVALID_HANDLE_VALUE; } if (process->process_handle != INVALID_HANDLE_VALUE) { CloseHandle(process->process_handle); process->process_handle = INVALID_HANDLE_VALUE; } } return err; }
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { int err; unsigned int i; uv_tcp_accept_t* req; if (handle->flags & UV_HANDLE_CONNECTION && handle->stream.conn.shutdown_req != NULL && handle->stream.conn.write_reqs_pending == 0) { UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); err = 0; if (handle->flags & UV_HANDLE_CLOSING) { err = ERROR_OPERATION_ABORTED; } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { err = WSAGetLastError(); } if (handle->stream.conn.shutdown_req->cb) { handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, uv_translate_sys_error(err)); } handle->stream.conn.shutdown_req = NULL; DECREASE_PENDING_REQ_COUNT(handle); return; } if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) { closesocket(handle->socket); handle->socket = INVALID_SOCKET; handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; } if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) { for (i = 0; i < uv_simultaneous_server_accepts; i++) { req = &handle->tcp.serv.accept_reqs[i]; if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; } if (req->event_handle) { CloseHandle(req->event_handle); req->event_handle = NULL; } } } uv__free(handle->tcp.serv.accept_reqs); handle->tcp.serv.accept_reqs = NULL; } if (handle->flags & UV_HANDLE_CONNECTION && handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(handle->read_req.wait_handle); handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } if (handle->read_req.event_handle) { CloseHandle(handle->read_req.event_handle); handle->read_req.event_handle = NULL; } } uv__handle_close(handle); loop->active_tcp_streams--; } }