From 251ec6e3e4c8552595c1e0ef735ca76573237565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Wed, 10 Nov 2010 17:42:04 +0300 Subject: [PATCH 2/2] Fix environment table generation for child processes --- src/util/os_priority.c | 172 +++++++++++++++++++++++++++++------------------- 1 files changed, 103 insertions(+), 69 deletions(-) diff --git a/src/util/os_priority.c b/src/util/os_priority.c index 10beff4..45ad63d 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c @@ -115,7 +115,7 @@ GNUNET_OS_install_parent_control_handler (void *cls, if (control_pipe == NULL) return; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe to the scheduler\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe %d to the scheduler\n", control_pipe_end[0]); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), GNUNET_OS_parent_control_handler, control_pipe); #endif } @@ -358,75 +358,100 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, } #if WINDOWS -/** - * Look through the @env_table and find its size (in bytes, excluding - * all NULL-terminators) and item count. - * - * Use count + size + 1 to calculate the size of the envtable in memory - * - * @param env_table environment table, as returned by GetEnvironmentStrings() - * @param count returned number of elements - * @param size returned total length of the items - * @return GNUNET_SYSERR on error, GNUNET_OK on success - */ -int -GetEnvTableSizeA (const char *env_table, size_t *count, size_t *size) +char * +CreateCustomEnvTable (char **vars) { + char *win32_env_table, *ptr, **var_ptr, *result, *result_ptr; size_t tablesize = 0; size_t items_count = 0; - const char *ptr; - if (!env_table) - return GNUNET_SYSERR; + size_t n_found = 0, n_var; + char *index = NULL; + size_t c; + size_t var_len; + char *var; + char *val; + win32_env_table = GetEnvironmentStringsA (); + if (win32_env_table == NULL) + return NULL; + for (c = 0, var_ptr = vars; *var_ptr; var_ptr += 2, c++); + n_var = c; + index = GNUNET_malloc (n_var); + for (c = 0; c < n_var; c++) + index[c] = 0; for (items_count = 0, ptr = win32_env_table; ptr[0] != 0; items_count++) { size_t len = strlen (ptr); - tablesize += len; - ptr += len + 1; + int found = 0; + for (var_ptr = vars; *var_ptr; var_ptr++) + { + var = *var_ptr++; + val = *var_ptr; + var_len = strlen (var); + if (strncmp (var, ptr, var_len) == 0) + { + found = 1; + index[c] = 1; + tablesize += var_len + strlen (val) + 1; + break; + } + } + if (!found) + tablesize += len + 1; + ptr += len + 1; } - if (count) - *count = items_count; - if (size) - *size = tablesize; - return GNUNET_OK; -} - -char * -CreateEnvTableA () -{ - char *result = NULL; - size_t count, size; - const char *win32_env_table; - win32_env_table = GetEnvironmentStrings (); - if (win32_env_table == NULL || GNUNET_OK != GetEnvTableSizeA (win32_env_table, &count, &size)) - return NULL; - result = GNUNET_malloc (count + size + 1); - if (result) - memcpy (result, win32_env_table, count + size + 1); - if (win32_env_table) - FreeEnvironmentStrings (win32_env_table); - return result; -} - -char * -AddToEnvTableA (char *env_table, const char *newvar) -{ - char *result = NULL, *ptr; - size_t count, size, new_var_size; - new_var_size = strlen (newvar); - if (env_table == NULL || GNUNET_OK != GetEnvTableSizeA ((const char *) env_table, &count, &size)) + for (n_found = 0, c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) { - GNUNET_free (env_table); - return NULL; + var = *var_ptr++; + val = *var_ptr; + if (index[c] != 1) + n_found += strlen (var) + strlen (val) + 1; + } + result = GNUNET_malloc (tablesize + n_found + 1); + for (result_ptr = result, ptr = win32_env_table; ptr[0] != 0;) + { + size_t len = strlen (ptr); + int found = 0; + for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) + { + var = *var_ptr++; + val = *var_ptr; + var_len = strlen (var); + if (strncmp (var, ptr, var_len) == 0) + { + found = 1; + break; + } + } + if (!found) + { + strcpy (result_ptr, ptr); + result_ptr += len + 1; + } + else + { + strcpy (result_ptr, var); + result_ptr += var_len; + strcpy (result_ptr, val); + result_ptr += strlen (val) + 1; + } + ptr += len + 1; } - result = GNUNET_malloc (count + 1 + size + new_var_size + 1); - if (result) + for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) { - memcpy (result, win32_env_table, count + size); - ptr = result + count + size; - memcpy (ptr, newvar, new_var_size + 1); - ptr[new_var_size + 1] = 0; + var = *var_ptr++; + val = *var_ptr; + var_len = strlen (var); + if (index[c] != 1) + { + strcpy (result_ptr, var); + result_ptr += var_len; + strcpy (result_ptr, val); + result_ptr += strlen (val) + 1; + } } - GNUNET_free (env_table); + FreeEnvironmentStrings (win32_env_table); + GNUNET_free (index); + *result_ptr = 0; return result; } #endif @@ -542,8 +567,8 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, PROCESS_INFORMATION proc; struct GNUNET_OS_Process *gnunet_proc = NULL; struct GNUNET_DISK_PipeHandle *control_pipe = NULL; - char *env_buf; char *env_block = NULL; + char *our_env[3] = { NULL, NULL, NULL }; HANDLE stdin_handle; HANDLE stdout_handle; @@ -593,10 +618,12 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE)); GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE)); - env_block = CreateEnvTableA (env_block); - GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end); - env_block = AddToEnvTableA (env_block, (const char *) env_buf); - GNUNET_free (env_buf); + GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_NT_CONTROL_PIPE); + GNUNET_asprintf (&our_env[1], "%d", control_pipe_read_end); + our_env[2] = NULL; + env_block = CreateCustomEnvTable (our_env); + GNUNET_free (our_env[0]); + GNUNET_free (our_env[1]); if (!CreateProcessA (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, env_block, NULL, &start, @@ -612,6 +639,8 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, gnunet_proc->handle = proc.hProcess; gnunet_proc->control_pipe = control_pipe; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started a child process, control pipe %d->%d\n", control_pipe_write_end, control_pipe_read_end); + CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); CloseHandle (proc.hThread); @@ -755,7 +784,8 @@ GNUNET_OS_start_process_v (const int *lsocks, char non_const_filename[MAX_PATH +1]; struct GNUNET_OS_Process *gnunet_proc = NULL; struct GNUNET_DISK_PipeHandle *control_pipe = NULL; - char *env_buf = NULL, *env_block = NULL; + char *env_block = NULL; + char *our_env[3] = { NULL, NULL, NULL }; HANDLE control_pipe_read_end, control_pipe_write_end; GNUNET_assert (lsocks == NULL); @@ -819,10 +849,12 @@ GNUNET_OS_start_process_v (const int *lsocks, GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE)); GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE)); - env_block = CreateEnvTableA (env_block); - GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end); - env_block = AddToEnvTableA (env_block, (const char *) env_buf); - GNUNET_free (env_buf); + GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_NT_CONTROL_PIPE); + GNUNET_asprintf (&our_env[1], "%d", control_pipe_read_end); + our_env[2] = NULL; + env_block = CreateCustomEnvTable (our_env); + GNUNET_free (our_env[0]); + GNUNET_free (our_env[1]); if (!CreateProcessA (non_const_filename, cmd, NULL, NULL, TRUE, @@ -834,6 +866,8 @@ GNUNET_OS_start_process_v (const int *lsocks, goto end; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started a child process, control pipe %d->%d\n", control_pipe_write_end, control_pipe_read_end); + gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = proc.dwProcessId; gnunet_proc->handle = proc.hProcess; -- 1.7.3.1.msysgit.0