aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2013-02-14 16:15:22 +0000
committerLRN <lrn1986@gmail.com>2013-02-14 16:15:22 +0000
commitf408da5bae9e316687069845a9da34a59df2eca8 (patch)
treef08ff875fbea7f43f25c1c93b20f85817b1ff878 /src/util
parentde1304424a62b8dee28118966414bd3ab9bd9fbc (diff)
downloadgnunet-f408da5bae9e316687069845a9da34a59df2eca8.tar.gz
gnunet-f408da5bae9e316687069845a9da34a59df2eca8.zip
Use passed-by-fd pipe to control chilren
Removes npipe_*() functions. Uses normal GNUnet pipe for child control (the pipe is anonymous on *nix, named-with-unique-name on W32). Also tighten W32 code (close pipes correctly on errors). Remove some FIXME NILS comments. Convert #if MINGW -> #if defined (WINDOWS) in some places. Better start_process() debug logging on W32
Diffstat (limited to 'src/util')
-rw-r--r--src/util/disk.c2
-rw-r--r--src/util/os_priority.c450
2 files changed, 149 insertions, 303 deletions
diff --git a/src/util/disk.c b/src/util/disk.c
index 53e8867e2..f06311f88 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -1866,7 +1866,7 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h)
1866 return ret; 1866 return ret;
1867} 1867}
1868 1868
1869#ifndef WINDOWS 1869#ifdef WINDOWS
1870/** 1870/**
1871 * Get a GNUnet file handle from a W32 handle. 1871 * Get a GNUnet file handle from a W32 handle.
1872 * 1872 *
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index 6074a1f24..2d5dba4a3 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -57,14 +57,10 @@ struct GNUNET_OS_Process
57#endif 57#endif
58 58
59 /** 59 /**
60 * Pipe we use to signal the process (if used). 60 * Pipe we use to signal the process.
61 * NULL if unused, or if process was deemed uncontrollable.
61 */ 62 */
62 struct GNUNET_DISK_FileHandle *control_pipe; 63 struct GNUNET_DISK_FileHandle *control_pipe;
63
64 /**
65 * Name of the pipe, NULL for none.
66 */
67 char *childpipename;
68}; 64};
69 65
70 66
@@ -74,244 +70,6 @@ struct GNUNET_OS_Process
74static struct GNUNET_OS_Process current_process; 70static struct GNUNET_OS_Process current_process;
75 71
76 72
77/* MinGW version of named pipe API */
78#ifdef MINGW
79/**
80 * Creates a named pipe/FIFO and opens it
81 *
82 * @param fn pointer to the name of the named pipe or to NULL,
83 * possibly updated to the new name (or free'd)
84 * @param flags open flags
85 * @param perm access permissions
86 * @return pipe handle on success, NULL on error
87 */
88static struct GNUNET_DISK_FileHandle *
89npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags,
90 enum GNUNET_DISK_AccessPermissions perm)
91{
92 struct GNUNET_DISK_FileHandle *ret;
93 HANDLE h = NULL;
94 DWORD openMode;
95 char *name;
96
97 openMode = 0;
98 if (flags & GNUNET_DISK_OPEN_READWRITE)
99 openMode = PIPE_ACCESS_DUPLEX;
100 else if (flags & GNUNET_DISK_OPEN_READ)
101 openMode = PIPE_ACCESS_INBOUND;
102 else if (flags & GNUNET_DISK_OPEN_WRITE)
103 openMode = PIPE_ACCESS_OUTBOUND;
104 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
105 openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
106
107 while (NULL == h)
108 {
109 DWORD error_code;
110
111 name = NULL;
112 if (NULL != *fn)
113 {
114 GNUNET_asprintf (&name, "\\\\.\\pipe\\%.246s", fn);
115 LOG (GNUNET_ERROR_TYPE_DEBUG,
116 "Trying to create an instance of named pipe `%s'\n", name);
117 /* 1) This might work just fine with UTF-8 strings as it is.
118 * 2) This is only used by GNUnet itself, and only with latin names.
119 */
120 h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED,
121 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
122 NULL);
123 }
124 else
125 {
126 GNUNET_asprintf (fn, "\\\\.\\pipe\\gnunet-%llu",
127 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
128 UINT64_MAX));
129 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n",
130 *fn);
131 h = CreateNamedPipe (*fn,
132 openMode | FILE_FLAG_OVERLAPPED |
133 FILE_FLAG_FIRST_PIPE_INSTANCE,
134 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
135 NULL);
136 }
137 error_code = GetLastError ();
138 GNUNET_free_non_null (name);
139 /* don't re-set name to NULL yet */
140 if (INVALID_HANDLE_VALUE == h)
141 {
142 SetErrnoFromWinError (error_code);
143 LOG (GNUNET_ERROR_TYPE_DEBUG,
144 "Pipe creation have failed because of %d, errno is %d\n", error_code,
145 errno);
146 if (NULL != *fn)
147 {
148 LOG (GNUNET_ERROR_TYPE_DEBUG,
149 "Pipe was to be unique, considering re-creation\n");
150 GNUNET_free (*fn);
151 *fn = NULL;
152 if ( (ERROR_ACCESS_DENIED != error_code) && (ERROR_PIPE_BUSY != error_code) )
153 return NULL;
154 LOG (GNUNET_ERROR_TYPE_DEBUG,
155 "Pipe name was not unique, trying again\n");
156 h = NULL;
157 }
158 else
159 return NULL;
160 }
161 }
162 ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
163 ret->h = h;
164 ret->type = GNUNET_DISK_HANLDE_TYPE_PIPE;
165 ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
166 ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
167 ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
168 ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
169 return ret;
170}
171
172
173/**
174 * Opens already existing named pipe/FIFO
175 *
176 * @param fn name of an existing named pipe
177 * @param flags open flags
178 * @return pipe handle on success, NULL on error
179 */
180static struct GNUNET_DISK_FileHandle *
181npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags)
182{
183 struct GNUNET_DISK_FileHandle *ret;
184 HANDLE h;
185 DWORD openMode;
186
187 openMode = 0;
188 if (flags & GNUNET_DISK_OPEN_READWRITE)
189 openMode = GENERIC_WRITE | GENERIC_READ;
190 else if (flags & GNUNET_DISK_OPEN_READ)
191 openMode = GENERIC_READ;
192 else if (flags & GNUNET_DISK_OPEN_WRITE)
193 openMode = GENERIC_WRITE;
194
195 h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING,
196 FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
197 if (INVALID_HANDLE_VALUE == h)
198 {
199 SetErrnoFromWinError (GetLastError ());
200 return NULL;
201 }
202
203 ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
204 ret->h = h;
205 ret->type = GNUNET_DISK_HANLDE_TYPE_PIPE;
206 ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
207 ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
208 ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
209 ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
210
211 return ret;
212}
213
214#else
215/* UNIX version of named-pipe API */
216
217/**
218 * Clean up a named pipe and the directory it was placed in.
219 *
220 * @param fn name of the pipe
221 */
222static void
223cleanup_npipe (const char *fn)
224{
225 char *dn;
226 char *dp;
227
228 if (0 != unlink (fn))
229 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
230 dn = GNUNET_strdup (fn);
231 dp = dirname (dn);
232 if (0 != rmdir (dp))
233 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rmdir", dp);
234 GNUNET_free (dn);
235}
236
237
238/**
239 * Setup a named pipe.
240 *
241 * @param fn where to store the name of the new pipe,
242 * if *fn is non-null, the name of the pipe to setup
243 * @return GNUNET_OK on success
244 */
245static int
246npipe_setup (char **fn)
247{
248 if (NULL == *fn)
249 {
250 /* FIXME: hardwired '/tmp' path... is bad */
251 char dir[] = "/tmp/gnunet-pipe-XXXXXX";
252
253 if (NULL == mkdtemp (dir))
254 {
255 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "mkdtemp");
256 return GNUNET_SYSERR;
257 }
258 GNUNET_asprintf (fn, "%s/child-control", dir);
259 }
260 if (-1 == mkfifo (*fn, S_IRUSR | S_IWUSR))
261 return GNUNET_SYSERR;
262 return GNUNET_OK;
263}
264
265
266/**
267 * Open an existing named pipe.
268 *
269 * @param fn name of the file
270 * @param flags flags to use
271 * @return NULL on error
272 */
273static struct GNUNET_DISK_FileHandle *
274npipe_open (const char *fn,
275 enum GNUNET_DISK_OpenFlags flags)
276{
277 struct GNUNET_DISK_FileHandle *ret;
278 int fd;
279 struct timespec req;
280 int i;
281
282 /* 200 * 5ms = 1s at most */
283 for (i=0;i<200;i++)
284 {
285 fd = open (fn, O_NONBLOCK | ((flags == GNUNET_DISK_OPEN_READ) ? O_RDONLY : O_WRONLY));
286 if ( (-1 != fd) || (9 == i) || (flags == GNUNET_DISK_OPEN_READ))
287 break;
288 /* as this is for killing a child process via pipe and it is conceivable that
289 the child process simply didn't finish starting yet, we do some sleeping
290 (which is obviously usually not allowed). We can't select on the FD as
291 'open' fails, and we probably shouldn't just "ignore" the error, so wait
292 and retry a few times is likely the best method; our process API doesn't
293 support continuations, so we need to sleep directly... */
294 req.tv_sec = 0;
295 req.tv_nsec = 5000000; /* 5ms */
296 (void) nanosleep (&req, NULL);
297 }
298 if (-1 == fd)
299 {
300 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
301 (flags == GNUNET_DISK_OPEN_READ)
302 ? _("Failed to open named pipe `%s' for reading: %s\n")
303 : _("Failed to open named pipe `%s' for writing: %s\n"),
304 fn,
305 STRERROR (errno));
306 return NULL;
307 }
308 ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
309 ret->fd = fd;
310 return ret;
311}
312#endif
313
314
315/** 73/**
316 * This handler is called when there are control data to be read on the pipe 74 * This handler is called when there are control data to be read on the pipe
317 * 75 *
@@ -323,8 +81,8 @@ parent_control_handler (void *cls,
323 const struct GNUNET_SCHEDULER_TaskContext *tc) 81 const struct GNUNET_SCHEDULER_TaskContext *tc)
324{ 82{
325 struct GNUNET_DISK_FileHandle *control_pipe = cls; 83 struct GNUNET_DISK_FileHandle *control_pipe = cls;
326 char *pipe_name;
327 char sig; 84 char sig;
85 char *pipe_fd;
328 ssize_t ret; 86 ssize_t ret;
329 87
330 LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, 88 LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__,
@@ -346,10 +104,10 @@ parent_control_handler (void *cls,
346 control_pipe = NULL; 104 control_pipe = NULL;
347 return; 105 return;
348 } 106 }
349 pipe_name = getenv (GNUNET_OS_CONTROL_PIPE); 107 pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE);
350 GNUNET_assert ( (NULL == pipe_name) || (strlen (pipe_name) <= 0) ); 108 GNUNET_assert ( (NULL == pipe_fd) || (strlen (pipe_fd) <= 0) );
351 LOG (GNUNET_ERROR_TYPE_DEBUG, 109 LOG (GNUNET_ERROR_TYPE_DEBUG,
352 "Got control code %d from parent via pipe %s\n", sig, pipe_name); 110 "Got control code %d from parent via pipe %s\n", sig, pipe_fd);
353 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 111 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
354 control_pipe, &parent_control_handler, 112 control_pipe, &parent_control_handler,
355 control_pipe); 113 control_pipe);
@@ -372,7 +130,9 @@ GNUNET_OS_install_parent_control_handler (void *cls,
372 GNUNET_SCHEDULER_TaskContext *tc) 130 GNUNET_SCHEDULER_TaskContext *tc)
373{ 131{
374 const char *env_buf; 132 const char *env_buf;
133 char *env_buf_end;
375 struct GNUNET_DISK_FileHandle *control_pipe; 134 struct GNUNET_DISK_FileHandle *control_pipe;
135 uint64_t pipe_fd;
376 136
377 env_buf = getenv (GNUNET_OS_CONTROL_PIPE); 137 env_buf = getenv (GNUNET_OS_CONTROL_PIPE);
378 if ( (NULL == env_buf) || (strlen (env_buf) <= 0) ) 138 if ( (NULL == env_buf) || (strlen (env_buf) <= 0) )
@@ -380,22 +140,34 @@ GNUNET_OS_install_parent_control_handler (void *cls,
380 LOG (GNUNET_ERROR_TYPE_DEBUG, 140 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "Not installing a handler because $%s is empty\n", 141 "Not installing a handler because $%s is empty\n",
382 GNUNET_OS_CONTROL_PIPE); 142 GNUNET_OS_CONTROL_PIPE);
383 putenv ("GNUNET_OS_CONTROL_PIPE="); 143 putenv (GNUNET_OS_CONTROL_PIPE "=");
144 return;
145 }
146 errno = 0;
147 pipe_fd = strtoull (env_buf, &env_buf_end, 16);
148 if ((0 != errno) || (env_buf == env_buf_end))
149 {
150 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "strtoull", env_buf);
151 putenv (GNUNET_OS_CONTROL_PIPE "=");
384 return; 152 return;
385 } 153 }
386 control_pipe = 154 /* Gcc will issue a warning here. What to do with it? */
387 npipe_open (env_buf, GNUNET_DISK_OPEN_READ); 155#if WINDOWS
156 control_pipe = GNUNET_DISK_get_handle_from_w32_handle ((HANDLE) pipe_fd);
157#else
158 control_pipe = GNUNET_DISK_get_handle_from_crt_fd ((int) pipe_fd);
159#endif
388 if (NULL == control_pipe) 160 if (NULL == control_pipe)
389 { 161 {
390 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf); 162 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf);
391 putenv ("GNUNET_OS_CONTROL_PIPE="); 163 putenv (GNUNET_OS_CONTROL_PIPE "=");
392 return; 164 return;
393 } 165 }
394 LOG (GNUNET_ERROR_TYPE_DEBUG, 166 LOG (GNUNET_ERROR_TYPE_DEBUG,
395 "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); 167 "Adding parent control handler pipe `%s' to the scheduler\n", env_buf);
396 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, 168 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe,
397 &parent_control_handler, control_pipe); 169 &parent_control_handler, control_pipe);
398 putenv ("GNUNET_OS_CONTROL_PIPE="); 170 putenv (GNUNET_OS_CONTROL_PIPE "=");
399} 171}
400 172
401 173
@@ -434,12 +206,6 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
434 char csig; 206 char csig;
435 207
436 csig = (char) sig; 208 csig = (char) sig;
437#if !WINDOWS
438 if ( (NULL == proc->control_pipe) &&
439 (NULL != proc->childpipename) )
440 proc->control_pipe = npipe_open (proc->childpipename,
441 GNUNET_DISK_OPEN_WRITE);
442#endif
443 if (NULL != proc->control_pipe) 209 if (NULL != proc->control_pipe)
444 { 210 {
445 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via pipe\n", sig, proc->pid); 211 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via pipe\n", sig, proc->pid);
@@ -450,13 +216,13 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
450 /* pipe failed or non-existent, try other methods */ 216 /* pipe failed or non-existent, try other methods */
451 switch (sig) 217 switch (sig)
452 { 218 {
453#if !WINDOWS 219#if !defined (WINDOWS)
454 case SIGHUP: 220 case SIGHUP:
455#endif 221#endif
456 case SIGINT: 222 case SIGINT:
457 case SIGKILL: 223 case SIGKILL:
458 case SIGTERM: 224 case SIGTERM:
459#if WINDOWS && !defined(__CYGWIN__) 225#if defined(WINDOWS) && !defined(__CYGWIN__)
460 { 226 {
461 DWORD exitcode; 227 DWORD exitcode;
462 int must_kill = GNUNET_YES; 228 int must_kill = GNUNET_YES;
@@ -496,7 +262,7 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
496 return PLIBC_KILL (proc->pid, sig); 262 return PLIBC_KILL (proc->pid, sig);
497#endif 263#endif
498 default: 264 default:
499#if WINDOWS 265#if defined (WINDOWS)
500 errno = EINVAL; 266 errno = EINVAL;
501 return -1; 267 return -1;
502#else 268#else
@@ -530,22 +296,13 @@ GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc)
530{ 296{
531 if (NULL != proc->control_pipe) 297 if (NULL != proc->control_pipe)
532 GNUNET_DISK_file_close (proc->control_pipe); 298 GNUNET_DISK_file_close (proc->control_pipe);
533// FIXME NILS 299#if defined (WINDOWS)
534#ifdef WINDOWS
535 if (proc->handle != NULL) 300 if (proc->handle != NULL)
536 CloseHandle (proc->handle); 301 CloseHandle (proc->handle);
537#endif 302#endif
538 if (NULL != proc->childpipename)
539 {
540#if !WINDOWS
541 cleanup_npipe (proc->childpipename);
542#endif
543 GNUNET_free (proc->childpipename);
544 }
545 GNUNET_free (proc); 303 GNUNET_free (proc);
546} 304}
547 305
548// FIXME NILS
549#if WINDOWS 306#if WINDOWS
550#include "gnunet_signal_lib.h" 307#include "gnunet_signal_lib.h"
551 308
@@ -851,7 +608,9 @@ start_process (int pipe_control,
851 char lpid[16]; 608 char lpid[16];
852 char fds[16]; 609 char fds[16];
853 struct GNUNET_OS_Process *gnunet_proc; 610 struct GNUNET_OS_Process *gnunet_proc;
854 char *childpipename = NULL; 611 struct GNUNET_DISK_FileHandle *childpipe_read;
612 struct GNUNET_DISK_FileHandle *childpipe_write;
613 int childpipe_read_fd;
855 int i; 614 int i;
856 int j; 615 int j;
857 int k; 616 int k;
@@ -866,11 +625,36 @@ start_process (int pipe_control,
866 625
867 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename)) 626 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename))
868 return NULL; /* not executable */ 627 return NULL; /* not executable */
869 if ( (GNUNET_YES == pipe_control) && 628 if (GNUNET_YES == pipe_control)
870 (GNUNET_OK != npipe_setup (&childpipename)) )
871 { 629 {
872 GNUNET_free (childpipename); 630 struct GNUNET_DISK_PipeHandle *childpipe;
873 return NULL; 631 int dup_childpipe_read_fd = -1;
632 childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
633 if (NULL == childpipe)
634 return NULL;
635 childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ);
636 childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE);
637 GNUNET_DISK_pipe_close (childpipe);
638 if ((NULL == childpipe_read) || (NULL == childpipe_write) ||
639 (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read,
640 &childpipe_read_fd, sizeof (int))) ||
641 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))))
642 {
643 if (childpipe_read)
644 GNUNET_DISK_file_close (childpipe_read);
645 if (childpipe_write)
646 GNUNET_DISK_file_close (childpipe_write);
647 if (0 <= dup_childpipe_read_fd)
648 close (dup_childpipe_read_fd);
649 return NULL;
650 }
651 childpipe_read_fd = dup_childpipe_read_fd;
652 GNUNET_DISK_file_close (childpipe_read);
653 }
654 else
655 {
656 childpipe_read = NULL;
657 childpipe_write = NULL;
874 } 658 }
875 if (NULL != pipe_stdout) 659 if (NULL != pipe_stdout)
876 { 660 {
@@ -913,10 +697,14 @@ start_process (int pipe_control,
913 if (-1 == ret) 697 if (-1 == ret)
914 { 698 {
915 int eno = errno; 699 int eno = errno;
916
917 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); 700 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
918 GNUNET_free_non_null (childpipename);
919 GNUNET_array_grow (lscp, ls, 0); 701 GNUNET_array_grow (lscp, ls, 0);
702 if (childpipe_read)
703 GNUNET_DISK_file_close (childpipe_read);
704 if (childpipe_write)
705 GNUNET_DISK_file_close (childpipe_write);
706 if (0 <= childpipe_read_fd)
707 close (childpipe_read_fd);
920 errno = eno; 708 errno = eno;
921 return NULL; 709 return NULL;
922 } 710 }
@@ -924,17 +712,23 @@ start_process (int pipe_control,
924 { 712 {
925 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 713 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
926 gnunet_proc->pid = ret; 714 gnunet_proc->pid = ret;
927 gnunet_proc->childpipename = childpipename; 715 gnunet_proc->control_pipe = childpipe_write;
716 if (GNUNET_YES == pipe_control)
717 {
718 close (childpipe_read_fd);
719 }
928 GNUNET_array_grow (lscp, ls, 0); 720 GNUNET_array_grow (lscp, ls, 0);
929 return gnunet_proc; 721 return gnunet_proc;
930 } 722 }
931 if (NULL != childpipename) 723 if (0 <= childpipe_read_fd)
932 { 724 {
933 setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); 725 char fdbuf[100];
934#ifndef DARWIN 726#ifndef DARWIN
935 /* due to vfork, we must NOT free memory on DARWIN! */ 727 /* due to vfork, we must NOT free memory on DARWIN! */
936 GNUNET_free (childpipename); 728 GNUNET_DISK_file_close (childpipe_write);
937#endif 729#endif
730 snprintf (fdbuf, 100, "%x", childpipe_read_fd);
731 setenv (GNUNET_OS_CONTROL_PIPE, fdbuf, 1);
938 } 732 }
939 if (NULL != pipe_stdin) 733 if (NULL != pipe_stdin)
940 { 734 {
@@ -1015,8 +809,9 @@ start_process (int pipe_control,
1015 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); 809 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
1016 _exit (1); 810 _exit (1);
1017#else 811#else
1018 struct GNUNET_DISK_FileHandle *control_pipe; 812 struct GNUNET_DISK_FileHandle *childpipe_read;
1019 char *childpipename = NULL; 813 struct GNUNET_DISK_FileHandle *childpipe_write;
814 HANDLE childpipe_read_handle;
1020 char **arg; 815 char **arg;
1021 char **non_const_argv; 816 char **non_const_argv;
1022 unsigned int cmdlen; 817 unsigned int cmdlen;
@@ -1027,7 +822,7 @@ start_process (int pipe_control,
1027 int argcount = 0; 822 int argcount = 0;
1028 struct GNUNET_OS_Process *gnunet_proc; 823 struct GNUNET_OS_Process *gnunet_proc;
1029 char path[MAX_PATH + 1]; 824 char path[MAX_PATH + 1];
1030 char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; 825 char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1031 char *env_block = NULL; 826 char *env_block = NULL;
1032 char *pathbuf; 827 char *pathbuf;
1033 DWORD pathbuf_len; 828 DWORD pathbuf_len;
@@ -1111,7 +906,11 @@ start_process (int pipe_control,
1111 * Remember: arguments to _start_process() are technically in UTF-8... 906 * Remember: arguments to _start_process() are technically in UTF-8...
1112 */ 907 */
1113 if (non_const_filename[1] == ':') 908 if (non_const_filename[1] == ':')
909 {
1114 snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); 910 snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename);
911 LOG (GNUNET_ERROR_TYPE_DEBUG,
912 "Using path `%s' as-is. PATH is %s\n", path, ptr);
913 }
1115 else if (!SearchPathA 914 else if (!SearchPathA
1116 (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), 915 (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char),
1117 path, NULL)) 916 path, NULL))
@@ -1123,6 +922,9 @@ start_process (int pipe_control,
1123 GNUNET_free (pathbuf); 922 GNUNET_free (pathbuf);
1124 return NULL; 923 return NULL;
1125 } 924 }
925 else
926 LOG (GNUNET_ERROR_TYPE_DEBUG,
927 "Found `%s' in PATH `%s'\n", path, pathbuf);
1126 GNUNET_free (pathbuf); 928 GNUNET_free (pathbuf);
1127 GNUNET_free (non_const_filename); 929 GNUNET_free (non_const_filename);
1128 930
@@ -1239,19 +1041,36 @@ start_process (int pipe_control,
1239 1041
1240 if (GNUNET_YES == pipe_control) 1042 if (GNUNET_YES == pipe_control)
1241 { 1043 {
1242 control_pipe = 1044 struct GNUNET_DISK_PipeHandle *childpipe;
1243 npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, 1045 childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
1244 GNUNET_DISK_PERM_USER_READ | 1046 if (NULL == childpipe)
1245 GNUNET_DISK_PERM_USER_WRITE); 1047 return NULL;
1246 if (control_pipe == NULL) 1048 childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ);
1049 childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE);
1050 GNUNET_DISK_pipe_close (childpipe);
1051 if ((NULL == childpipe_read) || (NULL == childpipe_write) ||
1052 (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read,
1053 &childpipe_read_handle, sizeof (HANDLE))))
1247 { 1054 {
1055 if (childpipe_read)
1056 GNUNET_DISK_file_close (childpipe_read);
1057 if (childpipe_write)
1058 GNUNET_DISK_file_close (childpipe_write);
1248 GNUNET_free (cmd); 1059 GNUNET_free (cmd);
1249 GNUNET_free (path); 1060 GNUNET_free (path);
1250 return NULL; 1061 return NULL;
1251 } 1062 }
1063 /* Unlike *nix variant, we don't dup the handle, so can't close
1064 * filehandle right now.
1065 */
1066 SetHandleInformation (childpipe_read_handle, HANDLE_FLAG_INHERIT, 1);
1252 } 1067 }
1253 else 1068 else
1254 control_pipe = NULL; 1069 {
1070 childpipe_read = NULL;
1071 childpipe_write = NULL;
1072 }
1073
1255 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) 1074 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
1256 { 1075 {
1257 lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); 1076 lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
@@ -1261,6 +1080,11 @@ start_process (int pipe_control,
1261 GNUNET_free (cmd); 1080 GNUNET_free (cmd);
1262 GNUNET_free (path); 1081 GNUNET_free (path);
1263 GNUNET_DISK_pipe_close (lsocks_pipe); 1082 GNUNET_DISK_pipe_close (lsocks_pipe);
1083 if (GNUNET_YES == pipe_control)
1084 {
1085 GNUNET_DISK_file_close (childpipe_write);
1086 GNUNET_DISK_file_close (childpipe_read);
1087 }
1264 return NULL; 1088 return NULL;
1265 } 1089 }
1266 lsocks_write_fd = GNUNET_DISK_pipe_handle (lsocks_pipe, 1090 lsocks_write_fd = GNUNET_DISK_pipe_handle (lsocks_pipe,
@@ -1271,15 +1095,14 @@ start_process (int pipe_control,
1271 (lsocks_pipe, GNUNET_DISK_PIPE_END_READ), 1095 (lsocks_pipe, GNUNET_DISK_PIPE_END_READ),
1272 &lsocks_read, sizeof (HANDLE)); 1096 &lsocks_read, sizeof (HANDLE));
1273 } 1097 }
1098 else
1099 lsocks_pipe = NULL;
1274 1100
1275 env_off = 0; 1101 env_off = 0;
1276 if (NULL != childpipename) 1102 if (GNUNET_YES == pipe_control)
1277 { 1103 {
1278 LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n",
1279 childpipename);
1280 GNUNET_asprintf (&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE); 1104 GNUNET_asprintf (&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE);
1281 GNUNET_asprintf (&our_env[env_off++], "%s", childpipename); 1105 GNUNET_asprintf (&our_env[env_off++], "%p", childpipe_read_handle);
1282 GNUNET_free (childpipename);
1283 } 1106 }
1284 if ( (lsocks != NULL) && (lsocks[0] != INVALID_SOCKET)) 1107 if ( (lsocks != NULL) && (lsocks[0] != INVALID_SOCKET))
1285 { 1108 {
@@ -1299,6 +1122,13 @@ start_process (int pipe_control,
1299 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno); 1122 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno);
1300 GNUNET_free (env_block); 1123 GNUNET_free (env_block);
1301 GNUNET_free (cmd); 1124 GNUNET_free (cmd);
1125 if (lsocks_pipe)
1126 GNUNET_DISK_pipe_close (lsocks_pipe);
1127 if (GNUNET_YES == pipe_control)
1128 {
1129 GNUNET_DISK_file_close (childpipe_write);
1130 GNUNET_DISK_file_close (childpipe_read);
1131 }
1302 return NULL; 1132 return NULL;
1303 } 1133 }
1304 1134
@@ -1310,6 +1140,13 @@ start_process (int pipe_control,
1310 GNUNET_free (env_block); 1140 GNUNET_free (env_block);
1311 GNUNET_free (cmd); 1141 GNUNET_free (cmd);
1312 free (wpath); 1142 free (wpath);
1143 if (lsocks_pipe)
1144 GNUNET_DISK_pipe_close (lsocks_pipe);
1145 if (GNUNET_YES == pipe_control)
1146 {
1147 GNUNET_DISK_file_close (childpipe_write);
1148 GNUNET_DISK_file_close (childpipe_read);
1149 }
1313 return NULL; 1150 return NULL;
1314 } 1151 }
1315 1152
@@ -1327,26 +1164,35 @@ start_process (int pipe_control,
1327 if (stdeh) 1164 if (stdeh)
1328 SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, stdef); 1165 SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, stdef);
1329 1166
1167 if (!bresult)
1168 LOG (GNUNET_ERROR_TYPE_ERROR, "CreateProcess(%s, %s) failed: %lu\n", path, cmd, error_code);
1169
1330 GNUNET_free (env_block); 1170 GNUNET_free (env_block);
1331 GNUNET_free (cmd); 1171 GNUNET_free (cmd);
1172 GNUNET_free (path);
1332 free (wpath); 1173 free (wpath);
1333 free (wcmd); 1174 free (wcmd);
1175 if (GNUNET_YES == pipe_control)
1176 {
1177 GNUNET_DISK_file_close (childpipe_read);
1178 }
1334 1179
1335 if (!bresult) 1180 if (!bresult)
1336 { 1181 {
1337 SetErrnoFromWinError (error_code); 1182 if (GNUNET_YES == pipe_control)
1338 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); 1183 {
1339 if (NULL != control_pipe) 1184 GNUNET_DISK_file_close (childpipe_write);
1340 GNUNET_DISK_file_close (control_pipe); 1185 }
1341 if (NULL != lsocks) 1186 if (NULL != lsocks)
1342 GNUNET_DISK_pipe_close (lsocks_pipe); 1187 GNUNET_DISK_pipe_close (lsocks_pipe);
1188 SetErrnoFromWinError (error_code);
1343 return NULL; 1189 return NULL;
1344 } 1190 }
1345 1191
1346 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); 1192 gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
1347 gnunet_proc->pid = proc.dwProcessId; 1193 gnunet_proc->pid = proc.dwProcessId;
1348 gnunet_proc->handle = proc.hProcess; 1194 gnunet_proc->handle = proc.hProcess;
1349 gnunet_proc->control_pipe = control_pipe; 1195 gnunet_proc->control_pipe = childpipe_write;
1350 1196
1351 CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL); 1197 CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL);
1352 1198