diff options
author | LRN <lrn1986@gmail.com> | 2013-02-14 16:15:22 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2013-02-14 16:15:22 +0000 |
commit | f408da5bae9e316687069845a9da34a59df2eca8 (patch) | |
tree | f08ff875fbea7f43f25c1c93b20f85817b1ff878 /src/util | |
parent | de1304424a62b8dee28118966414bd3ab9bd9fbc (diff) | |
download | gnunet-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.c | 2 | ||||
-rw-r--r-- | src/util/os_priority.c | 450 |
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 | |||
74 | static struct GNUNET_OS_Process current_process; | 70 | static 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 | */ | ||
88 | static struct GNUNET_DISK_FileHandle * | ||
89 | npipe_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 | */ | ||
180 | static struct GNUNET_DISK_FileHandle * | ||
181 | npipe_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 | */ | ||
222 | static void | ||
223 | cleanup_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 | */ | ||
245 | static int | ||
246 | npipe_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 | */ | ||
273 | static struct GNUNET_DISK_FileHandle * | ||
274 | npipe_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 | ||