Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

windows: implement uv_disable_stdio_inheritance

  • Loading branch information...
piscisaureus committed Jun 13, 2012
1 parent 94cb06f commit ade693024195716504416a2bbf3c87df05fb2022
Showing with 75 additions and 0 deletions.
  1. +16 −0 include/uv.h
  2. +4 −0 src/unix/core.c
  3. +1 −0 src/win/internal.h
  4. +54 −0 src/win/process-stdio.c
@@ -1580,6 +1580,22 @@ UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN extern uint64_t uv_hrtime(void);


/*
* Disables inheritance for file descriptors / handles that this process
* inherited from its parent. The effect is that child processes spawned by
* this proces don't accidently inherit these handles.
*
* It is recommended to call this function as early in your program as possible,
* before the inherited file descriptors can be closed or duplicated.
*
* Note that this function works on a best-effort basis: there is no guarantee
* that libuv can discover all file descriptors that were inherited. In general
* it does a better job on Windows than it does on unix.
*
* TODO(bb): insert snarky remark to annoy bnoordhuis and the folks at joyent.
*/
UV_EXTERN void uv_disable_stdio_inheritance(void);

/*
* Opens a shared library. The filename is in utf-8. Returns 0 on success and
* -1 on error. Call `uv_dlerror(uv_lib_t*)` to get the error message.
@@ -586,6 +586,10 @@ uv_err_t uv_chdir(const char* dir) {
}


void uv_disable_stdio_inheritance(void) {
}


static void uv__io_set_cb(uv__io_t* handle, uv__io_cb cb) {
union { void* data; uv__io_cb cb; } u;
u.cb = cb;
@@ -286,6 +286,7 @@ int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
BYTE** buffer_ptr);
void uv__stdio_destroy(BYTE* buffer);
void uv__stdio_noinherit(BYTE* buffer);
int uv__stdio_verify(BYTE* buffer, WORD size);
WORD uv__stdio_size(BYTE* buffer);
HANDLE uv__stdio_handle(BYTE* buffer, int fd);

@@ -64,6 +64,36 @@
#define FTEXT 0x80


/*
* Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited
* the parent process. Don't check for errors - the stdio handles may not be
* valid, or may be closed already. There is no guarantee that this function
* does a perfect job.
*/
void uv_disable_stdio_inheritance(void) {
HANDLE handle;
STARTUPINFOW si;

/* Make the windows stdio handles non-inheritable. */
handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);

handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);

handle = GetStdHandle(STD_ERROR_HANDLE);
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);

/* Make inherited CRT FDs non-inheritable. */
GetStartupInfoW(&si);
if (uv__stdio_verify(si.lpReserved2, si.cbReserved2))
uv__stdio_noinherit(si.lpReserved2);
}


static int uv__create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
HANDLE* child_pipe_ptr, unsigned int flags) {
char pipe_name[64];
@@ -415,6 +445,30 @@ void uv__stdio_noinherit(BYTE* buffer) {
}


int uv__stdio_verify(BYTE* buffer, WORD size) {
unsigned int count;

/* Check the buffer pointer. */
if (buffer == NULL)
return 0;

/* Verify that the buffer is at least big enough to hold the count. */
if (size < CHILD_STDIO_SIZE(0))
return 0;

/* Verify if the count is within range. */
count = CHILD_STDIO_COUNT(buffer);
if (count > 256)
return 0;

/* Verify that the buffer size is big enough to hold info for N FDs. */
if (size < CHILD_STDIO_SIZE(count))
return 0;

return 1;
}


WORD uv__stdio_size(BYTE* buffer) {
return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));
}

0 comments on commit ade6930

Please sign in to comment.
You can’t perform that action at this time.