aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac17
-rw-r--r--src/include/gnunet_disk_lib.h15
-rw-r--r--src/include/gnunet_os_lib.h8
-rw-r--r--src/util/disk.c133
-rw-r--r--src/util/network.c21
-rw-r--r--src/util/os_priority.c506
-rw-r--r--src/util/scheduler.c5
7 files changed, 635 insertions, 70 deletions
diff --git a/configure.ac b/configure.ac
index 8c747d283..6f6e47ea4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -755,6 +755,23 @@ AC_MSG_RESULT($enable_malicious)
755AM_CONDITIONAL([HAVE_MALICIOUS], [test "x$enable_malicious" = "x1"]) 755AM_CONDITIONAL([HAVE_MALICIOUS], [test "x$enable_malicious" = "x1"])
756AC_DEFINE_UNQUOTED([HAVE_MALICIOUS], $enable_malicious, [Compile malicious code]) 756AC_DEFINE_UNQUOTED([HAVE_MALICIOUS], $enable_malicious, [Compile malicious code])
757 757
758# should code be enabled that works around missing OS functionality on Windows?
759# used for test cases
760AC_ARG_ENABLE(windows_workarounds, [AS_HELP_STRING([--enable-windows_workarounds],
761 [enable workarounds used on Windows (only useful for test cases)])])
762if test $build_target = "mingw"
763then
764 workarounds=1
765else
766 if test x$enable_windows_workarounds = "xyes"
767 then
768 workarounds=1
769 else
770 workarounds=0
771 fi
772fi
773AC_DEFINE_UNQUOTED([ENABLE_WINDOWS_WORKAROUNDS], $workarounds, [enable workarounds used on Windows (only useful for test cases)])
774
758# gcov compilation 775# gcov compilation
759use_gcov=no 776use_gcov=no
760AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage], 777AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage],
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h
index a59d10ed0..383a9daa2 100644
--- a/src/include/gnunet_disk_lib.h
+++ b/src/include/gnunet_disk_lib.h
@@ -643,8 +643,19 @@ int GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h);
643int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h); 643int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h);
644 644
645/** 645/**
646 * Creates a named pipe/FIFO 646 * Creates a named pipe/FIFO and opens it
647 * @param fn name of the named pipe 647 * @param fn pointer to the name of the named pipe or to NULL
648 * @param flags open flags
649 * @param perm access permissions
650 * @return pipe handle on success, NULL on error
651 */
652struct GNUNET_DISK_FileHandle *GNUNET_DISK_npipe_create (char **fn,
653 enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm);
654
655/**
656 * Opens already existing named pipe/FIFO
657 *
658 * @param fn name of an existing named pipe
648 * @param flags open flags 659 * @param flags open flags
649 * @param perm access permissions 660 * @param perm access permissions
650 * @return pipe handle on success, NULL on error 661 * @return pipe handle on success, NULL on error
diff --git a/src/include/gnunet_os_lib.h b/src/include/gnunet_os_lib.h
index 5326e20cf..7bd65adcb 100644
--- a/src/include/gnunet_os_lib.h
+++ b/src/include/gnunet_os_lib.h
@@ -274,6 +274,14 @@ int GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
274int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc); 274int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc);
275 275
276 276
277/**
278 * Connects this process to its parent via pipe
279 */
280void
281GNUNET_OS_install_parent_control_handler (void *cls,
282 const struct
283 GNUNET_SCHEDULER_TaskContext * tc);
284
277#if 0 /* keep Emacsens' auto-indent happy */ 285#if 0 /* keep Emacsens' auto-indent happy */
278{ 286{
279#endif 287#endif
diff --git a/src/util/disk.c b/src/util/disk.c
index bb7929551..3c9469ca7 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -31,8 +31,10 @@
31#include "gnunet_disk_lib.h" 31#include "gnunet_disk_lib.h"
32#include "gnunet_scheduler_lib.h" 32#include "gnunet_scheduler_lib.h"
33#include "gnunet_strings_lib.h" 33#include "gnunet_strings_lib.h"
34#include "gnunet_crypto_lib.h"
34#include "disk.h" 35#include "disk.h"
35 36
37#define DEBUG_NPIPE GNUNET_YES
36 38
37/** 39/**
38 * Block size for IO for copying files. 40 * Block size for IO for copying files.
@@ -1876,20 +1878,20 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
1876 1878
1877 1879
1878/** 1880/**
1879 * Creates a named pipe/FIFO 1881 * Creates a named pipe/FIFO and opens it
1880 * @param fn name of the named pipe 1882 * @param fn pointer to the name of the named pipe or to NULL
1881 * @param flags open flags 1883 * @param flags open flags
1882 * @param perm access permissions 1884 * @param perm access permissions
1883 * @return pipe handle on success, NULL on error 1885 * @return pipe handle on success, NULL on error
1884 */ 1886 */
1885struct GNUNET_DISK_FileHandle * 1887struct GNUNET_DISK_FileHandle *
1886GNUNET_DISK_npipe_open (const char *fn, 1888GNUNET_DISK_npipe_create (char **fn,
1887 enum GNUNET_DISK_OpenFlags flags, 1889 enum GNUNET_DISK_OpenFlags flags,
1888 enum GNUNET_DISK_AccessPermissions perm) 1890 enum GNUNET_DISK_AccessPermissions perm)
1889{ 1891{
1890#ifdef MINGW 1892#ifdef MINGW
1891 struct GNUNET_DISK_FileHandle *ret; 1893 struct GNUNET_DISK_FileHandle *ret;
1892 HANDLE h; 1894 HANDLE h = NULL;
1893 DWORD openMode; 1895 DWORD openMode;
1894 char *name; 1896 char *name;
1895 1897
@@ -1904,22 +1906,80 @@ GNUNET_DISK_npipe_open (const char *fn,
1904 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) 1906 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1905 openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; 1907 openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
1906 1908
1907 GNUNET_asprintf(&name, "\\\\.\\pipe\\pipename\\%s", fn); 1909 while (h == NULL)
1908 h = CreateNamedPipe (fn, openMode | FILE_FLAG_OVERLAPPED,
1909 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL);
1910 GNUNET_free(name);
1911 if (h == NULL)
1912 { 1910 {
1913 SetErrnoFromWinError(GetLastError()); 1911 DWORD error_code;
1914 return NULL; 1912 name = NULL;
1913 if (*fn != NULL)
1914 {
1915 GNUNET_asprintf(&name, "\\\\.\\pipe\\%.246s", fn);
1916#if DEBUG_NPIPE
1917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to create an instance of named pipe `%s'\n", name);
1918#endif
1919 h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED,
1920 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL);
1921 }
1922 else
1923 {
1924 GNUNET_asprintf(fn, "\\\\.\\pipe\\gnunet-%llu",
1925 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX));
1926#if DEBUG_NPIPE
1927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n", *fn);
1928#endif
1929 h = CreateNamedPipe (*fn, openMode | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
1930 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL);
1931 }
1932 error_code = GetLastError ();
1933 if (name)
1934 GNUNET_free(name);
1935 /* don't re-set name to NULL yet */
1936 if (h == INVALID_HANDLE_VALUE)
1937 {
1938 SetErrnoFromWinError(error_code);
1939#if DEBUG_NPIPE
1940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe creation have failed because of %d, errno is %d\n", error_code, errno);
1941#endif
1942 if (name == NULL)
1943 {
1944#if DEBUG_NPIPE
1945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe was to be unique, considering re-creation\n");
1946#endif
1947 GNUNET_free (*fn);
1948 *fn = NULL;
1949 if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY)
1950 {
1951 return NULL;
1952 }
1953#if DEBUG_NPIPE
1954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe name was not unique, trying again\n");
1955#endif
1956 h = NULL;
1957 }
1958 else
1959 return NULL;
1960 }
1915 } 1961 }
1962 errno = 0;
1916 1963
1917 ret = GNUNET_malloc(sizeof(*ret)); 1964 ret = GNUNET_malloc(sizeof(*ret));
1918 ret->h = h; 1965 ret->h = h;
1966 ret->type = GNUNET_PIPE;
1919 1967
1920 return ret; 1968 return ret;
1921#else 1969#else
1922 if (mkfifo(fn, translate_unix_perms(perm)) == -1) 1970 if (*fn == NULL)
1971 {
1972 char dir[] = "/tmp/gnunet-pipe-XXXXXX";
1973
1974 if (mkdtemp(dir) == NULL)
1975 {
1976 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "mkdtemp");
1977 return NULL;
1978 }
1979 GNUNET_asprintf(fn, "%s/child-control", dir);
1980 }
1981
1982 if (mkfifo(*fn, translate_unix_perms(perm)) == -1)
1923 { 1983 {
1924 if ( (errno != EEXIST) || 1984 if ( (errno != EEXIST) ||
1925 (0 != (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) ) 1985 (0 != (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) )
@@ -1932,6 +1992,51 @@ GNUNET_DISK_npipe_open (const char *fn,
1932} 1992}
1933 1993
1934/** 1994/**
1995 * Opens already existing named pipe/FIFO
1996 *
1997 * @param fn name of an existing named pipe
1998 * @param flags open flags
1999 * @param perm access permissions
2000 * @return pipe handle on success, NULL on error
2001 */
2002struct GNUNET_DISK_FileHandle *
2003GNUNET_DISK_npipe_open (const char *fn,
2004 enum GNUNET_DISK_OpenFlags flags,
2005 enum GNUNET_DISK_AccessPermissions perm)
2006{
2007#ifdef MINGW
2008 struct GNUNET_DISK_FileHandle *ret;
2009 HANDLE h;
2010 DWORD openMode;
2011
2012 openMode = 0;
2013 if (flags & GNUNET_DISK_OPEN_READWRITE)
2014 openMode = GENERIC_WRITE | GENERIC_READ;
2015 else if (flags & GNUNET_DISK_OPEN_READ)
2016 openMode = GENERIC_READ;
2017 else if (flags & GNUNET_DISK_OPEN_WRITE)
2018 openMode = GENERIC_WRITE;
2019
2020 h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING,
2021 FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
2022 if (h == INVALID_HANDLE_VALUE)
2023 {
2024 SetErrnoFromWinError(GetLastError());
2025 return NULL;
2026 }
2027
2028 ret = GNUNET_malloc(sizeof(*ret));
2029 ret->h = h;
2030 ret->type = GNUNET_PIPE;
2031
2032 return ret;
2033#else
2034 flags = flags & (~GNUNET_DISK_OPEN_FAILIFEXISTS);
2035 return GNUNET_DISK_file_open(fn, flags, perm);
2036#endif
2037}
2038
2039/**
1935 * Closes a named pipe/FIFO 2040 * Closes a named pipe/FIFO
1936 * @param pipe named pipe 2041 * @param pipe named pipe
1937 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise 2042 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
diff --git a/src/util/network.c b/src/util/network.c
index 08121928d..9e85a3be9 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -1127,15 +1127,26 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1127 { 1127 {
1128 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) 1128 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1129 { 1129 {
1130 retcode = -1; 1130 DWORD error_code = GetLastError ();
1131 SetErrnoFromWinError (GetLastError ()); 1131 switch (error_code)
1132 {
1133 case ERROR_BROKEN_PIPE:
1134 GNUNET_CONTAINER_slist_add (handles_read,
1135 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1136 fh, sizeof (struct GNUNET_DISK_FileHandle));
1137 retcode++;
1138 break;
1139 default:
1140 retcode = -1;
1141 SetErrnoFromWinError (error_code);
1132 1142
1133 #if DEBUG_NETWORK 1143 #if DEBUG_NETWORK
1134 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 1144 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1135 "PeekNamedPipe"); 1145 "PeekNamedPipe");
1136 1146
1137 #endif 1147 #endif
1138 goto select_loop_end; 1148 goto select_loop_end;
1149 }
1139 } 1150 }
1140 else if (dwBytes) 1151 else if (dwBytes)
1141 1152
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index fb6c2922c..e9ca9deea 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -27,29 +27,87 @@
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_common.h" 28#include "gnunet_common.h"
29#include "gnunet_os_lib.h" 29#include "gnunet_os_lib.h"
30#include "gnunet_scheduler_lib.h"
30#include "disk.h" 31#include "disk.h"
31 32
33#define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE"
34
32struct GNUNET_OS_Process 35struct GNUNET_OS_Process
33{ 36{
34 pid_t pid; 37 pid_t pid;
35#if WINDOWS 38#if WINDOWS
36 HANDLE handle; 39 HANDLE handle;
37#endif 40#endif
41 int sig;
42 struct GNUNET_DISK_FileHandle *control_pipe;
38}; 43};
39 44
40static struct GNUNET_OS_Process current_process; 45static struct GNUNET_OS_Process current_process;
41 46
42 47
43#if WINDOWS 48/**
49 * This handler is called when there are control data to be read on the pipe
50 */
44void 51void
45GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle) 52GNUNET_OS_parent_control_handler (void *cls,
53 const struct
54 GNUNET_SCHEDULER_TaskContext * tc)
46{ 55{
47 if (proc->handle != NULL) 56 struct GNUNET_DISK_FileHandle *control_pipe = (struct GNUNET_DISK_FileHandle *) cls;
48 CloseHandle (proc->handle); 57 int sig;
49 proc->handle = handle; 58
59 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, tc->reason);
60
61 if (tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | GNUNET_SCHEDULER_REASON_PREREQ_DONE))
62 {
63 GNUNET_DISK_npipe_close (control_pipe);
64 }
65 else
66 {
67 if (GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig)) != sizeof (sig))
68 {
69 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read");
70 GNUNET_DISK_npipe_close (control_pipe);
71 }
72 else
73 {
74 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent\n", sig);
75 raise (sig);
76 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-scheduling the parent control handler pipe\n");
77 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, GNUNET_OS_parent_control_handler, control_pipe);
78 }
79 }
50} 80}
51#endif
52 81
82/**
83 * Connects this process to its parent via pipe
84 */
85void
86GNUNET_OS_install_parent_control_handler (void *cls,
87 const struct
88 GNUNET_SCHEDULER_TaskContext * tc)
89{
90 char *env_buf;
91 struct GNUNET_DISK_FileHandle *control_pipe = NULL;
92
93 env_buf = getenv (GNUNET_OS_CONTROL_PIPE);
94 if (env_buf == NULL || strlen (env_buf) <= 0)
95 {
96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not installing a handler because %s=%s\n", GNUNET_OS_CONTROL_PIPE, env_buf);
97 return;
98 }
99
100 control_pipe = GNUNET_DISK_npipe_open (env_buf, GNUNET_DISK_OPEN_READ,
101 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
102 if (control_pipe == NULL)
103 {
104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to open the pipe `%s'\n", env_buf);
105 return;
106 }
107
108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe `%s' to the scheduler\n", env_buf);
109 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, GNUNET_OS_parent_control_handler, control_pipe);
110}
53 111
54/** 112/**
55 * Get process structure for current process 113 * Get process structure for current process
@@ -74,28 +132,60 @@ GNUNET_OS_process_current ()
74int 132int
75GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) 133GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
76{ 134{
77#if WINDOWS 135#if ENABLE_WINDOWS_WORKAROUNDS
78 if (sig == SIGKILL || sig == SIGTERM) 136 int res;
137 int ret;
138
139 ret = GNUNET_DISK_file_write (proc->control_pipe, &sig, sizeof(sig));
140 if (ret != sizeof(sig))
79 { 141 {
80 HANDLE h = proc->handle; 142 if (errno == ECOMM)
81 if (NULL == h) 143 /* Child process is not controllable via pipe */
82 { 144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 145 "Child process is not controllable, will kill it directly\n");
84 _("Invalid process information {%d, %08X}\n"),
85 proc->pid,
86 h);
87 return -1;
88 }
89 if (!TerminateProcess (h, 0))
90 {
91 SetErrnoFromWinError (GetLastError ());
92 return -1;
93 }
94 else 146 else
95 return 0; 147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 "Failed to write into control pipe , errno is %d\n", errno);
149 res = PLIBC_KILL (proc->pid, sig);
96 } 150 }
97 errno = EINVAL; 151 else
98 return -1; 152 {
153 struct GNUNET_NETWORK_FDSet *rfds;
154 struct GNUNET_NETWORK_FDSet *efds;
155
156 rfds = GNUNET_NETWORK_fdset_create ();
157 efds = GNUNET_NETWORK_fdset_create ();
158
159 GNUNET_NETWORK_fdset_handle_set (rfds, proc->control_pipe);
160 GNUNET_NETWORK_fdset_handle_set (efds, proc->control_pipe);
161
162 read_next:
163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
164 "Wrote control code into control pipe, now waiting\n");
165
166 ret = GNUNET_NETWORK_socket_select (rfds, NULL, efds,
167 GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_unit (),
168 5000));
169
170 if (ret < 1 || GNUNET_NETWORK_fdset_handle_isset (efds,
171 proc->control_pipe))
172 {
173 /* Just to be sure */
174 PLIBC_KILL (proc->pid, sig);
175 res = 0;
176 }
177 else
178 {
179 if (GNUNET_DISK_file_read (proc->control_pipe, &ret,
180 sizeof(ret)) != GNUNET_OK)
181 res = PLIBC_KILL (proc->pid, sig);
182
183 /* Child signaled shutdown is in progress */
184 goto read_next;
185 }
186 }
187
188 return res;
99#else 189#else
100 return kill (proc->pid, sig); 190 return kill (proc->pid, sig);
101#endif 191#endif
@@ -117,13 +207,19 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc)
117void 207void
118GNUNET_OS_process_close (struct GNUNET_OS_Process *proc) 208GNUNET_OS_process_close (struct GNUNET_OS_Process *proc)
119{ 209{
120#if WINDOWS 210#if ENABLE_WINDOWS_WORKAROUNDS
211 if (proc->control_pipe)
212 GNUNET_DISK_npipe_close (proc->control_pipe);
213#endif
214// FIXME NILS
215#ifdef WINDOWS
121 if (proc->handle != NULL) 216 if (proc->handle != NULL)
122 CloseHandle (proc->handle); 217 CloseHandle (proc->handle);
123#endif 218#endif
124 GNUNET_free (proc); 219 GNUNET_free (proc);
125} 220}
126 221
222// FIXME NILS
127#if WINDOWS 223#if WINDOWS
128#include "gnunet_signal_lib.h" 224#include "gnunet_signal_lib.h"
129 225
@@ -258,6 +354,105 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
258 return GNUNET_OK; 354 return GNUNET_OK;
259} 355}
260 356
357#if MINGW
358static char *
359CreateCustomEnvTable (char **vars)
360{
361 char *win32_env_table, *ptr, **var_ptr, *result, *result_ptr;
362 size_t tablesize = 0;
363 size_t items_count = 0;
364 size_t n_found = 0, n_var;
365 char *index = NULL;
366 size_t c;
367 size_t var_len;
368 char *var;
369 char *val;
370 win32_env_table = GetEnvironmentStringsA ();
371 if (win32_env_table == NULL)
372 return NULL;
373 for (c = 0, var_ptr = vars; *var_ptr; var_ptr += 2, c++);
374 n_var = c;
375 index = GNUNET_malloc (n_var);
376 for (c = 0; c < n_var; c++)
377 index[c] = 0;
378 for (items_count = 0, ptr = win32_env_table; ptr[0] != 0; items_count++)
379 {
380 size_t len = strlen (ptr);
381 int found = 0;
382 for (var_ptr = vars; *var_ptr; var_ptr++)
383 {
384 var = *var_ptr++;
385 val = *var_ptr;
386 var_len = strlen (var);
387 if (strncmp (var, ptr, var_len) == 0)
388 {
389 found = 1;
390 index[c] = 1;
391 tablesize += var_len + strlen (val) + 1;
392 break;
393 }
394 }
395 if (!found)
396 tablesize += len + 1;
397 ptr += len + 1;
398 }
399 for (n_found = 0, c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++)
400 {
401 var = *var_ptr++;
402 val = *var_ptr;
403 if (index[c] != 1)
404 n_found += strlen (var) + strlen (val) + 1;
405 }
406 result = GNUNET_malloc (tablesize + n_found + 1);
407 for (result_ptr = result, ptr = win32_env_table; ptr[0] != 0;)
408 {
409 size_t len = strlen (ptr);
410 int found = 0;
411 for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++)
412 {
413 var = *var_ptr++;
414 val = *var_ptr;
415 var_len = strlen (var);
416 if (strncmp (var, ptr, var_len) == 0)
417 {
418 found = 1;
419 break;
420 }
421 }
422 if (!found)
423 {
424 strcpy (result_ptr, ptr);
425 result_ptr += len + 1;
426 }
427 else
428 {
429 strcpy (result_ptr, var);
430 result_ptr += var_len;
431 strcpy (result_ptr, val);
432 result_ptr += strlen (val) + 1;
433 }
434 ptr += len + 1;
435 }
436 for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++)
437 {
438 var = *var_ptr++;
439 val = *var_ptr;
440 var_len = strlen (var);
441 if (index[c] != 1)
442 {
443 strcpy (result_ptr, var);
444 result_ptr += var_len;
445 strcpy (result_ptr, val);
446 result_ptr += strlen (val) + 1;
447 }
448 }
449 FreeEnvironmentStrings (win32_env_table);
450 GNUNET_free (index);
451 *result_ptr = 0;
452 return result;
453}
454#endif
455
261/** 456/**
262 * Start a process. 457 * Start a process.
263 * 458 *
@@ -273,10 +468,14 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
273 const char *filename, ...) 468 const char *filename, ...)
274{ 469{
275 va_list ap; 470 va_list ap;
471#if ENABLE_WINDOWS_WORKAROUNDS
472 char *childpipename = NULL;
473 struct GNUNET_DISK_FileHandle *control_pipe = NULL;
474#endif
475 struct GNUNET_OS_Process *gnunet_proc = NULL;
276 476
277#ifndef MINGW 477#ifndef MINGW
278 pid_t ret; 478 pid_t ret;
279 struct GNUNET_OS_Process *gnunet_proc = NULL;
280 char **argv; 479 char **argv;
281 int argc; 480 int argc;
282 int fd_stdout_write; 481 int fd_stdout_write;
@@ -284,6 +483,14 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
284 int fd_stdin_read; 483 int fd_stdin_read;
285 int fd_stdin_write; 484 int fd_stdin_write;
286 485
486#if ENABLE_WINDOWS_WORKAROUNDS
487 control_pipe = GNUNET_DISK_npipe_create (&childpipename,
488 GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ |
489 GNUNET_DISK_PERM_USER_WRITE);
490 if (control_pipe == NULL)
491 return NULL;
492#endif
493
287 argc = 0; 494 argc = 0;
288 va_start (ap, filename); 495 va_start (ap, filename);
289 while (NULL != va_arg (ap, char *)) 496 while (NULL != va_arg (ap, char *))
@@ -316,6 +523,9 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
316 if (ret == -1) 523 if (ret == -1)
317 { 524 {
318 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); 525 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
526#if ENABLE_WINDOWS_WORKAROUNDS
527 GNUNET_DISK_npipe_close (control_pipe);
528#endif
319 } 529 }
320 else 530 else
321 { 531 {
@@ -337,11 +547,22 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
337#endif 547#endif
338 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 548 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
339 gnunet_proc->pid = ret; 549 gnunet_proc->pid = ret;
550#if ENABLE_WINDOWS_WORKAROUNDS
551 gnunet_proc->control_pipe = control_pipe;
552#endif
340 } 553 }
341 GNUNET_free (argv); 554 GNUNET_free (argv);
555#if ENABLE_WINDOWS_WORKAROUNDS
556 GNUNET_free (childpipename);
557#endif
342 return gnunet_proc; 558 return gnunet_proc;
343 } 559 }
344 560
561#if ENABLE_WINDOWS_WORKAROUNDS
562 setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1);
563 GNUNET_free (childpipename);
564#endif
565
345 if (pipe_stdout != NULL) 566 if (pipe_stdout != NULL)
346 { 567 {
347 GNUNET_break (0 == close (fd_stdout_read)); 568 GNUNET_break (0 == close (fd_stdout_read));
@@ -367,23 +588,84 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
367 char *cmd, *idx; 588 char *cmd, *idx;
368 STARTUPINFO start; 589 STARTUPINFO start;
369 PROCESS_INFORMATION proc; 590 PROCESS_INFORMATION proc;
370 struct GNUNET_OS_Process *gnunet_proc = NULL;
371 591
372 HANDLE stdin_handle; 592 HANDLE stdin_handle;
373 HANDLE stdout_handle; 593 HANDLE stdout_handle;
374 594
375 char path[MAX_PATH + 1]; 595 char path[MAX_PATH + 1];
376 596
597 char *our_env[3] = { NULL, NULL, NULL };
598 char *env_block = NULL;
599 char *pathbuf;
600 DWORD pathbuf_len, alloc_len;
601 char *self_prefix;
602 char *bindir;
603 char *libdir;
604 char *ptr;
605 char *non_const_filename;
606
607 /* Search in prefix dir (hopefully - the directory from which
608 * the current module was loaded), bindir and libdir, then in PATH
609 */
610 self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX);
611 bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
612 libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
613
614 pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0);
615
616 alloc_len = pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + strlen (libdir);
617
618 pathbuf = GNUNET_malloc (alloc_len * sizeof (char));
619
620 ptr = pathbuf;
621 ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
622 GNUNET_free (self_prefix);
623 GNUNET_free (bindir);
624 GNUNET_free (libdir);
625
626 alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len);
627 GNUNET_assert (alloc_len == (pathbuf_len - 1));
628
629 cmdlen = strlen (filename);
630 if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0)
631 GNUNET_asprintf (&non_const_filename, "%s.exe", filename);
632 else
633 GNUNET_asprintf (&non_const_filename, "%s", filename);
634
635 /* Check that this is the full path. If it isn't, search. */
636 if (non_const_filename[1] == ':')
637 snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename);
638 else if (!SearchPathA (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), path, NULL))
639 {
640 SetErrnoFromWinError (GetLastError ());
641 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "SearchPath", non_const_filename);
642 GNUNET_free (non_const_filename);
643 GNUNET_free (pathbuf);
644 return NULL;
645 }
646 GNUNET_free (pathbuf);
647 GNUNET_free (non_const_filename);
648
377 cmdlen = 0; 649 cmdlen = 0;
378 va_start (ap, filename); 650 va_start (ap, filename);
379 while (NULL != (arg = va_arg (ap, char *))) 651 while (NULL != (arg = va_arg (ap, char *)))
380 cmdlen = cmdlen + strlen (arg) + 3; 652 {
653 if (cmdlen == 0)
654 cmdlen = cmdlen + strlen (path) + 3;
655 else
656 cmdlen = cmdlen + strlen (arg) + 3;
657 }
381 va_end (ap); 658 va_end (ap);
382 659
383 cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); 660 cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1));
384 va_start (ap, filename); 661 va_start (ap, filename);
385 while (NULL != (arg = va_arg (ap, char *))) 662 while (NULL != (arg = va_arg (ap, char *)))
386 idx += sprintf (idx, "\"%s\" ", arg); 663 {
664 if (idx == cmd)
665 idx += sprintf (idx, "\"%s\" ", path);
666 else
667 idx += sprintf (idx, "\"%s\" ", arg);
668 }
387 va_end (ap); 669 va_end (ap);
388 670
389 memset (&start, 0, sizeof (start)); 671 memset (&start, 0, sizeof (start));
@@ -404,28 +686,46 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
404 start.hStdOutput = stdout_handle; 686 start.hStdOutput = stdout_handle;
405 } 687 }
406 688
407 if (32 >= (int) FindExecutableA (filename, NULL, path)) 689 control_pipe = GNUNET_DISK_npipe_create (&childpipename,
408 { 690 GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ |
409 SetErrnoFromWinError (GetLastError ()); 691 GNUNET_DISK_PERM_USER_WRITE);
410 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); 692 if (control_pipe == NULL)
411 return NULL; 693 {
412 } 694 GNUNET_free (cmd);
695 GNUNET_free (path);
696 return NULL;
697 }
698
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", childpipename);
700
701 GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE);
702 GNUNET_asprintf (&our_env[1], "%s", childpipename);
703 our_env[2] = NULL;
704 env_block = CreateCustomEnvTable (our_env);
705 GNUNET_free (our_env[0]);
706 GNUNET_free (our_env[1]);
413 707
414 if (!CreateProcessA 708 if (!CreateProcessA
415 (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start, 709 (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
416 &proc)) 710 env_block, NULL, &start, &proc))
417 { 711 {
418 SetErrnoFromWinError (GetLastError ()); 712 SetErrnoFromWinError (GetLastError ());
419 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); 713 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path);
714 GNUNET_free (env_block);
715 GNUNET_free (cmd);
420 return NULL; 716 return NULL;
421 } 717 }
422 718
719 GNUNET_free (env_block);
720
423 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 721 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
424 gnunet_proc->pid = proc.dwProcessId; 722 gnunet_proc->pid = proc.dwProcessId;
425 gnunet_proc->handle = proc.hProcess; 723 gnunet_proc->handle = proc.hProcess;
724 gnunet_proc->control_pipe = control_pipe;
426 725
427 CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); 726 CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
428 727
728 ResumeThread (proc.hThread);
429 CloseHandle (proc.hThread); 729 CloseHandle (proc.hThread);
430 730
431 GNUNET_free (cmd); 731 GNUNET_free (cmd);
@@ -450,6 +750,11 @@ struct GNUNET_OS_Process *
450GNUNET_OS_start_process_v (const int *lsocks, 750GNUNET_OS_start_process_v (const int *lsocks,
451 const char *filename, char *const argv[]) 751 const char *filename, char *const argv[])
452{ 752{
753#if ENABLE_WINDOWS_WORKAROUNDS
754 struct GNUNET_DISK_FileHandle *control_pipe = NULL;
755 char *childpipename = NULL;
756#endif
757
453#ifndef MINGW 758#ifndef MINGW
454 pid_t ret; 759 pid_t ret;
455 char lpid[16]; 760 char lpid[16];
@@ -463,6 +768,14 @@ GNUNET_OS_start_process_v (const int *lsocks,
463 int *lscp; 768 int *lscp;
464 unsigned int ls; 769 unsigned int ls;
465 770
771#if ENABLE_WINDOWS_WORKAROUNDS
772 control_pipe = GNUNET_DISK_npipe_create (&childpipename,
773 GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ |
774 GNUNET_DISK_PERM_USER_WRITE);
775 if (control_pipe == NULL)
776 return NULL;
777#endif
778
466 lscp = NULL; 779 lscp = NULL;
467 ls = 0; 780 ls = 0;
468 if (lsocks != NULL) 781 if (lsocks != NULL)
@@ -482,6 +795,9 @@ GNUNET_OS_start_process_v (const int *lsocks,
482 if (ret == -1) 795 if (ret == -1)
483 { 796 {
484 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); 797 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
798#if ENABLE_WINDOWS_WORKAROUNDS
799 GNUNET_DISK_npipe_close (control_pipe);
800#endif
485 } 801 }
486 else 802 else
487 { 803 {
@@ -498,10 +814,23 @@ GNUNET_OS_start_process_v (const int *lsocks,
498#endif 814#endif
499 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 815 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
500 gnunet_proc->pid = ret; 816 gnunet_proc->pid = ret;
817#if ENABLE_WINDOWS_WORKAROUNDS
818 gnunet_proc->control_pipe = control_pipe;
819
820#endif
501 } 821 }
502 GNUNET_array_grow (lscp, ls, 0); 822 GNUNET_array_grow (lscp, ls, 0);
823#if ENABLE_WINDOWS_WORKAROUNDS
824 GNUNET_free (childpipename);
825#endif
503 return gnunet_proc; 826 return gnunet_proc;
504 } 827 }
828
829#if ENABLE_WINDOWS_WORKAROUNDS
830 setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1);
831 GNUNET_free (childpipename);
832#endif
833
505 if (lscp != NULL) 834 if (lscp != NULL)
506 { 835 {
507 /* read systemd documentation... */ 836 /* read systemd documentation... */
@@ -555,17 +884,68 @@ GNUNET_OS_start_process_v (const int *lsocks,
555 STARTUPINFO start; 884 STARTUPINFO start;
556 PROCESS_INFORMATION proc; 885 PROCESS_INFORMATION proc;
557 int argcount = 0; 886 int argcount = 0;
558 char non_const_filename[MAX_PATH +1];
559 struct GNUNET_OS_Process *gnunet_proc = NULL; 887 struct GNUNET_OS_Process *gnunet_proc = NULL;
560 888
889 char path[MAX_PATH + 1];
890
891 char *our_env[3] = { NULL, NULL, NULL };
892 char *env_block = NULL;
893 char *pathbuf;
894 DWORD pathbuf_len, alloc_len;
895 char *self_prefix;
896 char *bindir;
897 char *libdir;
898 char *ptr;
899 char *non_const_filename;
900
561 GNUNET_assert (lsocks == NULL); 901 GNUNET_assert (lsocks == NULL);
562 902
563 if (32 >= (int) FindExecutableA (filename, NULL, non_const_filename)) 903 /* Search in prefix dir (hopefully - the directory from which
904 * the current module was loaded), bindir and libdir, then in PATH
905 */
906 self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX);
907 bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
908 libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
909
910 pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0);
911
912 alloc_len = pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + strlen (libdir);
913
914 pathbuf = GNUNET_malloc (alloc_len * sizeof (char));
915
916 ptr = pathbuf;
917 ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
918 GNUNET_free (self_prefix);
919 GNUNET_free (bindir);
920 GNUNET_free (libdir);
921
922 alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len);
923 if (alloc_len != pathbuf_len - 1)
924 {
925 GNUNET_free (pathbuf);
926 errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */
927 return NULL;
928 }
929
930 cmdlen = strlen (filename);
931 if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0)
932 GNUNET_asprintf (&non_const_filename, "%s.exe", filename);
933 else
934 GNUNET_asprintf (&non_const_filename, "%s", filename);
935
936 /* Check that this is the full path. If it isn't, search. */
937 if (non_const_filename[1] == ':')
938 snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename);
939 else if (!SearchPathA (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), path, NULL))
564 { 940 {
565 SetErrnoFromWinError (GetLastError ()); 941 SetErrnoFromWinError (GetLastError ());
566 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); 942 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "SearchPath", non_const_filename);
943 GNUNET_free (non_const_filename);
944 GNUNET_free (pathbuf);
567 return NULL; 945 return NULL;
568 } 946 }
947 GNUNET_free (pathbuf);
948 GNUNET_free (non_const_filename);
569 949
570 /* Count the number of arguments */ 950 /* Count the number of arguments */
571 arg = (char **) argv; 951 arg = (char **) argv;
@@ -583,7 +963,10 @@ GNUNET_OS_start_process_v (const int *lsocks,
583 arg = (char **) argv; 963 arg = (char **) argv;
584 while (*arg) 964 while (*arg)
585 { 965 {
586 non_const_argv[argcount] = GNUNET_strdup (*arg); 966 if (arg == argv)
967 non_const_argv[argcount] = GNUNET_strdup (path);
968 else
969 non_const_argv[argcount] = GNUNET_strdup (*arg);
587 arg++; 970 arg++;
588 argcount++; 971 argcount++;
589 } 972 }
@@ -607,31 +990,56 @@ GNUNET_OS_start_process_v (const int *lsocks,
607 arg++; 990 arg++;
608 } 991 }
609 992
993 while (argcount > 0)
994 GNUNET_free (non_const_argv[--argcount]);
995 GNUNET_free (non_const_argv);
996
610 memset (&start, 0, sizeof (start)); 997 memset (&start, 0, sizeof (start));
611 start.cb = sizeof (start); 998 start.cb = sizeof (start);
612 999
1000 control_pipe = GNUNET_DISK_npipe_create (&childpipename,
1001 GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ |
1002 GNUNET_DISK_PERM_USER_WRITE);
1003 if (control_pipe == NULL)
1004 {
1005 GNUNET_free (cmd);
1006 GNUNET_free (path);
1007 return NULL;
1008 }
1009
1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", childpipename);
1011
1012 GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE);
1013 GNUNET_asprintf (&our_env[1], "%s", childpipename);
1014 our_env[2] = NULL;
1015 env_block = CreateCustomEnvTable (our_env);
1016 GNUNET_free (our_env[0]);
1017 GNUNET_free (our_env[1]);
1018
613 if (!CreateProcess 1019 if (!CreateProcess
614 (non_const_filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start, 1020 (path, cmd, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED,
615 &proc)) 1021 env_block, NULL, &start, &proc))
616 { 1022 {
617 SetErrnoFromWinError (GetLastError ()); 1023 SetErrnoFromWinError (GetLastError ());
618 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); 1024 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess");
1025 GNUNET_free (env_block);
1026 GNUNET_free (cmd);
619 return NULL; 1027 return NULL;
620 } 1028 }
621 1029
1030 GNUNET_free (env_block);
1031
622 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 1032 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
623 gnunet_proc->pid = proc.dwProcessId; 1033 gnunet_proc->pid = proc.dwProcessId;
624 gnunet_proc->handle = proc.hProcess; 1034 gnunet_proc->handle = proc.hProcess;
1035 gnunet_proc->control_pipe = control_pipe;
625 1036
626 CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); 1037 CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
627 1038
1039 ResumeThread (proc.hThread);
628 CloseHandle (proc.hThread); 1040 CloseHandle (proc.hThread);
629 GNUNET_free (cmd); 1041 GNUNET_free (cmd);
630 1042
631 while (argcount > 0)
632 GNUNET_free (non_const_argv[--argcount]);
633 GNUNET_free (non_const_argv);
634
635 return gnunet_proc; 1043 return gnunet_proc;
636#endif 1044#endif
637} 1045}
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 8a6479929..2d7907395 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -739,6 +739,11 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
739 GNUNET_SCHEDULER_add_continuation (task, 739 GNUNET_SCHEDULER_add_continuation (task,
740 task_cls, 740 task_cls,
741 GNUNET_SCHEDULER_REASON_STARTUP); 741 GNUNET_SCHEDULER_REASON_STARTUP);
742#if ENABLE_WINDOWS_WORKAROUNDS
743 GNUNET_SCHEDULER_add_continuation (GNUNET_OS_install_parent_control_handler,
744 NULL, GNUNET_SCHEDULER_REASON_STARTUP);
745#endif
746
742 last_tr = 0; 747 last_tr = 0;
743 busy_wait_warning = 0; 748 busy_wait_warning = 0;
744 while ((pending != NULL) || 749 while ((pending != NULL) ||