diff options
Diffstat (limited to 'src/util/os_priority.c')
-rw-r--r-- | src/util/os_priority.c | 688 |
1 files changed, 428 insertions, 260 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index 64dce4ba3..18dc4edaa 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -39,21 +39,252 @@ | |||
39 | 39 | ||
40 | #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" | 40 | #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" |
41 | 41 | ||
42 | #define DEBUG_OS GNUNET_EXTRA_LOGGING | ||
43 | |||
44 | struct GNUNET_OS_Process | 42 | struct GNUNET_OS_Process |
45 | { | 43 | { |
44 | /** | ||
45 | * PID of the process. | ||
46 | */ | ||
46 | pid_t pid; | 47 | pid_t pid; |
48 | |||
47 | #if WINDOWS | 49 | #if WINDOWS |
50 | /** | ||
51 | * Process handle. | ||
52 | */ | ||
48 | HANDLE handle; | 53 | HANDLE handle; |
49 | #endif | 54 | #endif |
50 | int sig; | 55 | |
56 | /** | ||
57 | * Pipe we use to signal the process (if used). | ||
58 | */ | ||
51 | struct GNUNET_DISK_FileHandle *control_pipe; | 59 | struct GNUNET_DISK_FileHandle *control_pipe; |
60 | |||
61 | /** | ||
62 | * Name of the pipe, NULL for none. | ||
63 | */ | ||
64 | char *childpipename; | ||
52 | }; | 65 | }; |
53 | 66 | ||
67 | |||
68 | /** | ||
69 | * Handle for 'this' process. | ||
70 | */ | ||
54 | static struct GNUNET_OS_Process current_process; | 71 | static struct GNUNET_OS_Process current_process; |
55 | 72 | ||
56 | 73 | ||
74 | /* MinGW version of named pipe API */ | ||
75 | #ifdef MINGW | ||
76 | /** | ||
77 | * Creates a named pipe/FIFO and opens it | ||
78 | * | ||
79 | * @param fn pointer to the name of the named pipe or to NULL | ||
80 | * @param flags open flags | ||
81 | * @param perm access permissions | ||
82 | * @return pipe handle on success, NULL on error | ||
83 | */ | ||
84 | static struct GNUNET_DISK_FileHandle * | ||
85 | npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags, | ||
86 | enum GNUNET_DISK_AccessPermissions perm) | ||
87 | { | ||
88 | struct GNUNET_DISK_FileHandle *ret; | ||
89 | HANDLE h = NULL; | ||
90 | DWORD openMode; | ||
91 | char *name; | ||
92 | |||
93 | openMode = 0; | ||
94 | if (flags & GNUNET_DISK_OPEN_READWRITE) | ||
95 | openMode = PIPE_ACCESS_DUPLEX; | ||
96 | else if (flags & GNUNET_DISK_OPEN_READ) | ||
97 | openMode = PIPE_ACCESS_INBOUND; | ||
98 | else if (flags & GNUNET_DISK_OPEN_WRITE) | ||
99 | openMode = PIPE_ACCESS_OUTBOUND; | ||
100 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) | ||
101 | openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; | ||
102 | |||
103 | while (h == NULL) | ||
104 | { | ||
105 | DWORD error_code; | ||
106 | |||
107 | name = NULL; | ||
108 | if (*fn != NULL) | ||
109 | { | ||
110 | GNUNET_asprintf (&name, "\\\\.\\pipe\\%.246s", fn); | ||
111 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
112 | "Trying to create an instance of named pipe `%s'\n", name); | ||
113 | /* 1) This might work just fine with UTF-8 strings as it is. | ||
114 | * 2) This is only used by GNUnet itself, and only with latin names. | ||
115 | */ | ||
116 | h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED, | ||
117 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, | ||
118 | NULL); | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | GNUNET_asprintf (fn, "\\\\.\\pipe\\gnunet-%llu", | ||
123 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
124 | UINT64_MAX)); | ||
125 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n", | ||
126 | *fn); | ||
127 | h = CreateNamedPipe (*fn, | ||
128 | openMode | FILE_FLAG_OVERLAPPED | | ||
129 | FILE_FLAG_FIRST_PIPE_INSTANCE, | ||
130 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, | ||
131 | NULL); | ||
132 | } | ||
133 | error_code = GetLastError (); | ||
134 | if (name) | ||
135 | GNUNET_free (name); | ||
136 | /* don't re-set name to NULL yet */ | ||
137 | if (h == INVALID_HANDLE_VALUE) | ||
138 | { | ||
139 | SetErrnoFromWinError (error_code); | ||
140 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Pipe creation have failed because of %d, errno is %d\n", error_code, | ||
142 | errno); | ||
143 | if (name == NULL) | ||
144 | { | ||
145 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
146 | "Pipe was to be unique, considering re-creation\n"); | ||
147 | GNUNET_free (*fn); | ||
148 | *fn = NULL; | ||
149 | if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY) | ||
150 | { | ||
151 | return NULL; | ||
152 | } | ||
153 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
154 | "Pipe name was not unique, trying again\n"); | ||
155 | h = NULL; | ||
156 | } | ||
157 | else | ||
158 | return NULL; | ||
159 | } | ||
160 | } | ||
161 | errno = 0; | ||
162 | |||
163 | ret = GNUNET_malloc (sizeof (*ret)); | ||
164 | ret->h = h; | ||
165 | ret->type = GNUNET_PIPE; | ||
166 | ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
167 | ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
168 | ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
169 | ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Opens already existing named pipe/FIFO | ||
176 | * | ||
177 | * @param fn name of an existing named pipe | ||
178 | * @param flags open flags | ||
179 | * @param perm access permissions | ||
180 | * @return pipe handle on success, NULL on error | ||
181 | */ | ||
182 | static struct GNUNET_DISK_FileHandle * | ||
183 | npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, | ||
184 | enum GNUNET_DISK_AccessPermissions perm) | ||
185 | { | ||
186 | struct GNUNET_DISK_FileHandle *ret; | ||
187 | HANDLE h; | ||
188 | DWORD openMode; | ||
189 | |||
190 | openMode = 0; | ||
191 | if (flags & GNUNET_DISK_OPEN_READWRITE) | ||
192 | openMode = GENERIC_WRITE | GENERIC_READ; | ||
193 | else if (flags & GNUNET_DISK_OPEN_READ) | ||
194 | openMode = GENERIC_READ; | ||
195 | else if (flags & GNUNET_DISK_OPEN_WRITE) | ||
196 | openMode = GENERIC_WRITE; | ||
197 | |||
198 | h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING, | ||
199 | FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL); | ||
200 | if (h == INVALID_HANDLE_VALUE) | ||
201 | { | ||
202 | SetErrnoFromWinError (GetLastError ()); | ||
203 | return NULL; | ||
204 | } | ||
205 | |||
206 | ret = GNUNET_malloc (sizeof (*ret)); | ||
207 | ret->h = h; | ||
208 | ret->type = GNUNET_PIPE; | ||
209 | ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
210 | ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
211 | ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
212 | ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | #else | ||
218 | /* UNIX version of named-pipe API */ | ||
219 | |||
220 | /** | ||
221 | * Clean up a named pipe and the directory it was placed in. | ||
222 | * | ||
223 | * @param fn name of the pipe | ||
224 | */ | ||
225 | static void | ||
226 | cleanup_npipe (const char *fn) | ||
227 | { | ||
228 | char *dn; | ||
229 | char *dp; | ||
230 | |||
231 | if (0 != unlink (fn)) | ||
232 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); | ||
233 | dn = GNUNET_strdup (fn); | ||
234 | dp = dirname (dn); | ||
235 | if (0 != rmdir (dp)) | ||
236 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rmdir", dp); | ||
237 | GNUNET_free (dn); | ||
238 | } | ||
239 | |||
240 | |||
241 | /** | ||
242 | * Setup a named pipe. | ||
243 | * | ||
244 | * @param fn where to store the name of the new pipe, | ||
245 | * if *fn is non-null, the name of the pipe to setup | ||
246 | * @return GNUNET_OK on success | ||
247 | */ | ||
248 | static int | ||
249 | npipe_setup (char **fn) | ||
250 | { | ||
251 | if (NULL == *fn) | ||
252 | { | ||
253 | /* FIXME: hardwired '/tmp' path... is bad */ | ||
254 | char dir[] = "/tmp/gnunet-pipe-XXXXXX"; | ||
255 | |||
256 | if (NULL == mkdtemp (dir)) | ||
257 | { | ||
258 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "mkdtemp"); | ||
259 | return GNUNET_SYSERR; | ||
260 | } | ||
261 | GNUNET_asprintf (fn, "%s/child-control", dir); | ||
262 | } | ||
263 | if (-1 == mkfifo (*fn, S_IRUSR | S_IWUSR)) | ||
264 | return GNUNET_SYSERR; | ||
265 | return GNUNET_OK; | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Open an existing named pipe. | ||
271 | * | ||
272 | * @param fn name of the file | ||
273 | * @param flags flags to use | ||
274 | * @param perm permissions to use | ||
275 | * @return NULL on error | ||
276 | */ | ||
277 | static struct GNUNET_DISK_FileHandle * | ||
278 | npipe_open (const char *fn, | ||
279 | enum GNUNET_DISK_OpenFlags flags, | ||
280 | enum GNUNET_DISK_AccessPermissions perm) | ||
281 | { | ||
282 | flags = flags & (~GNUNET_DISK_OPEN_FAILIFEXISTS); | ||
283 | return GNUNET_DISK_file_open (fn, flags, perm); | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | |||
57 | /** | 288 | /** |
58 | * This handler is called when there are control data to be read on the pipe | 289 | * This handler is called when there are control data to be read on the pipe |
59 | * | 290 | * |
@@ -64,44 +295,41 @@ static void | |||
64 | parent_control_handler (void *cls, | 295 | parent_control_handler (void *cls, |
65 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 296 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
66 | { | 297 | { |
67 | struct GNUNET_DISK_FileHandle *control_pipe = | 298 | struct GNUNET_DISK_FileHandle *control_pipe = cls; |
68 | (struct GNUNET_DISK_FileHandle *) cls; | ||
69 | int sig; | 299 | int sig; |
70 | 300 | ||
71 | #if DEBUG_OS | ||
72 | LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, | 301 | LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, |
73 | tc->reason); | 302 | tc->reason); |
74 | #endif | ||
75 | if (tc->reason & | 303 | if (tc->reason & |
76 | (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | | 304 | (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | |
77 | GNUNET_SCHEDULER_REASON_PREREQ_DONE)) | 305 | GNUNET_SCHEDULER_REASON_PREREQ_DONE)) |
78 | { | 306 | { |
79 | GNUNET_DISK_npipe_close (control_pipe); | 307 | GNUNET_DISK_file_close (control_pipe); |
308 | return; | ||
80 | } | 309 | } |
81 | else | 310 | if (GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig)) != |
311 | sizeof (sig)) | ||
82 | { | 312 | { |
83 | if (GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig)) != | 313 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); |
84 | sizeof (sig)) | 314 | GNUNET_DISK_file_close (control_pipe); |
85 | { | 315 | return; |
86 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); | ||
87 | GNUNET_DISK_npipe_close (control_pipe); | ||
88 | } | ||
89 | else | ||
90 | { | ||
91 | #if DEBUG_OS | ||
92 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent\n", sig); | ||
93 | #endif | ||
94 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
95 | control_pipe, &parent_control_handler, | ||
96 | control_pipe); | ||
97 | raise (sig); | ||
98 | } | ||
99 | } | 316 | } |
317 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent\n", sig); | ||
318 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
319 | control_pipe, &parent_control_handler, | ||
320 | control_pipe); | ||
321 | raise (sig); | ||
100 | } | 322 | } |
101 | 323 | ||
102 | 324 | ||
103 | /** | 325 | /** |
104 | * Task that connects this process to its parent via pipe | 326 | * Task that connects this process to its parent via pipe; |
327 | * essentially, the parent control handler will read signal numbers | ||
328 | * from the 'GNUNET_OS_CONTROL_PIPE' (as given in an environment | ||
329 | * variable) and raise those signals. | ||
330 | * | ||
331 | * @param cls closure (unused) | ||
332 | * @param tc scheduler context (unused) | ||
105 | */ | 333 | */ |
106 | void | 334 | void |
107 | GNUNET_OS_install_parent_control_handler (void *cls, | 335 | GNUNET_OS_install_parent_control_handler (void *cls, |
@@ -112,27 +340,26 @@ GNUNET_OS_install_parent_control_handler (void *cls, | |||
112 | struct GNUNET_DISK_FileHandle *control_pipe; | 340 | struct GNUNET_DISK_FileHandle *control_pipe; |
113 | 341 | ||
114 | env_buf = getenv (GNUNET_OS_CONTROL_PIPE); | 342 | env_buf = getenv (GNUNET_OS_CONTROL_PIPE); |
115 | if ((env_buf == NULL) || (strlen (env_buf) <= 0)) | 343 | if ( (env_buf == NULL) || (strlen (env_buf) <= 0) ) |
116 | { | 344 | { |
117 | LOG (GNUNET_ERROR_TYPE_INFO, _("Not installing a handler because $%s=%s\n"), | 345 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
118 | GNUNET_OS_CONTROL_PIPE, env_buf); | 346 | "Not installing a handler because $%s is empty\n", |
347 | GNUNET_OS_CONTROL_PIPE); | ||
119 | putenv ("GNUNET_OS_CONTROL_PIPE="); | 348 | putenv ("GNUNET_OS_CONTROL_PIPE="); |
120 | return; | 349 | return; |
121 | } | 350 | } |
122 | control_pipe = | 351 | control_pipe = |
123 | GNUNET_DISK_npipe_open (env_buf, GNUNET_DISK_OPEN_READ, | 352 | npipe_open (env_buf, GNUNET_DISK_OPEN_READ, |
124 | GNUNET_DISK_PERM_USER_READ | | 353 | GNUNET_DISK_PERM_USER_READ | |
125 | GNUNET_DISK_PERM_USER_WRITE); | 354 | GNUNET_DISK_PERM_USER_WRITE); |
126 | if (control_pipe == NULL) | 355 | if (NULL == control_pipe) |
127 | { | 356 | { |
128 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf); | 357 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf); |
129 | putenv ("GNUNET_OS_CONTROL_PIPE="); | 358 | putenv ("GNUNET_OS_CONTROL_PIPE="); |
130 | return; | 359 | return; |
131 | } | 360 | } |
132 | #if DEBUG_OS | ||
133 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 361 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
134 | "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); | 362 | "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); |
135 | #endif | ||
136 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, | 363 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, |
137 | &parent_control_handler, control_pipe); | 364 | &parent_control_handler, control_pipe); |
138 | putenv ("GNUNET_OS_CONTROL_PIPE="); | 365 | putenv ("GNUNET_OS_CONTROL_PIPE="); |
@@ -160,104 +387,64 @@ GNUNET_OS_process_current () | |||
160 | } | 387 | } |
161 | 388 | ||
162 | 389 | ||
390 | /** | ||
391 | * Sends a signal to the process | ||
392 | * | ||
393 | * @param proc pointer to process structure | ||
394 | * @param sig signal | ||
395 | * @return 0 on success, -1 on error | ||
396 | */ | ||
163 | int | 397 | int |
164 | GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) | 398 | GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) |
165 | { | 399 | { |
166 | #if ENABLE_WINDOWS_WORKAROUNDS | 400 | int ret; |
167 | int res = 0; | ||
168 | int ret = 0; | ||
169 | 401 | ||
402 | #if !WINDOWS | ||
403 | if ( (NULL == proc->control_pipe) && | ||
404 | (NULL != proc->childpipename) ) | ||
405 | proc->control_pipe = npipe_open (proc->childpipename, | ||
406 | GNUNET_DISK_OPEN_WRITE, | ||
407 | GNUNET_DISK_PERM_USER_READ | | ||
408 | GNUNET_DISK_PERM_USER_WRITE); | ||
409 | #endif | ||
410 | if (NULL == proc->control_pipe) | ||
411 | { | ||
412 | #if WINDOWS | ||
413 | /* no pipe and windows? can't do this */ | ||
414 | errno = EINVAL; | ||
415 | return -1; | ||
416 | #else | ||
417 | return kill (proc->pid, sig); | ||
418 | #endif | ||
419 | } | ||
170 | ret = GNUNET_DISK_file_write (proc->control_pipe, &sig, sizeof (sig)); | 420 | ret = GNUNET_DISK_file_write (proc->control_pipe, &sig, sizeof (sig)); |
171 | if (ret != sizeof (sig)) | 421 | if (ret == sizeof (sig)) |
422 | return 0; | ||
423 | /* pipe failed, try other methods */ | ||
424 | switch (sig) | ||
172 | { | 425 | { |
173 | if (errno == ECOMM) | 426 | case SIGHUP: |
174 | { | 427 | case SIGINT: |
175 | /* Child process is not controllable via pipe */ | 428 | case SIGKILL: |
176 | #if DEBUG_OS | 429 | case SIGTERM: |
177 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 430 | #if WINDOWS && !defined(__CYGWIN__) |
178 | "Child process is not controllable, will kill it directly\n"); | 431 | if (0 == TerminateProcess (proc->handle, 0)) |
179 | #endif | ||
180 | } | ||
181 | else if (errno == EPIPE) | ||
182 | { | 432 | { |
183 | #if DEBUG_OS | 433 | /* FIXME: set 'errno' */ |
184 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 434 | return -1; |
185 | "Failed to write into control pipe, because pipe is invalid (the child is most likely dead)\n"); | ||
186 | #endif | ||
187 | } | 435 | } |
188 | else | 436 | return 0; |
189 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
190 | "Failed to write into control pipe , errno is %d\n", errno); | ||
191 | #if WINDOWS && !defined(__CYGWIN__) | ||
192 | TerminateProcess (proc->handle, 0); | ||
193 | #else | 437 | #else |
194 | PLIBC_KILL (proc->pid, sig); | 438 | return PLIBC_KILL (proc->pid, sig); |
195 | #endif | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | #if DEBUG_OS | ||
200 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
201 | "Wrote control code into control pipe, now waiting\n"); | ||
202 | #endif | 439 | #endif |
203 | 440 | default: | |
204 | #if WINDOWS | 441 | #if WINDOWS |
205 | /* Give it 3 seconds to die, then kill it in a nice Windows-specific way */ | 442 | errno = EINVAL; |
206 | if (WaitForSingleObject (proc->handle, 3000) != WAIT_OBJECT_0) | 443 | return -1; |
207 | TerminateProcess (proc->handle, 0); | ||
208 | res = 0; | ||
209 | #else | 444 | #else |
210 | struct GNUNET_NETWORK_FDSet *rfds; | 445 | return kill (proc->pid, sig); |
211 | struct GNUNET_NETWORK_FDSet *efds; | 446 | #endif |
212 | |||
213 | rfds = GNUNET_NETWORK_fdset_create (); | ||
214 | efds = GNUNET_NETWORK_fdset_create (); | ||
215 | |||
216 | GNUNET_NETWORK_fdset_handle_set (rfds, proc->control_pipe); | ||
217 | GNUNET_NETWORK_fdset_handle_set (efds, proc->control_pipe); | ||
218 | |||
219 | /* Ndurner thought this up, and i have no idea what it does. | ||
220 | * There's have never been any code to answer the shutdown call | ||
221 | * (write a single int into the pipe, so that this function can read it). | ||
222 | * On *nix select() will probably tell that pipe is ready | ||
223 | * for reading, once the other process shuts down, | ||
224 | * but the read () call will fail, triggering a kill () | ||
225 | * on the pid that is already dead. This will probably result in non-0 | ||
226 | * return from kill(), and therefore from this function. | ||
227 | */ | ||
228 | while (1) | ||
229 | { | ||
230 | ret = | ||
231 | GNUNET_NETWORK_socket_select (rfds, NULL, efds, | ||
232 | GNUNET_TIME_relative_multiply | ||
233 | (GNUNET_TIME_relative_get_unit (), | ||
234 | 5000)); | ||
235 | |||
236 | if (ret < 1 || | ||
237 | GNUNET_NETWORK_fdset_handle_isset (efds, proc->control_pipe)) | ||
238 | { | ||
239 | /* Just to be sure */ | ||
240 | PLIBC_KILL (proc->pid, sig); | ||
241 | res = 0; | ||
242 | break; | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | if (GNUNET_DISK_file_read (proc->control_pipe, &ret, sizeof (ret)) != | ||
247 | GNUNET_OK) | ||
248 | res = PLIBC_KILL (proc->pid, sig); | ||
249 | |||
250 | /* Child signaled shutdown is in progress */ | ||
251 | continue; | ||
252 | } | ||
253 | } | ||
254 | #endif | ||
255 | } | 447 | } |
256 | |||
257 | return res; | ||
258 | #else | ||
259 | return kill (proc->pid, sig); | ||
260 | #endif | ||
261 | } | 448 | } |
262 | 449 | ||
263 | /** | 450 | /** |
@@ -279,13 +466,18 @@ GNUNET_OS_process_close (struct GNUNET_OS_Process *proc) | |||
279 | { | 466 | { |
280 | #if ENABLE_WINDOWS_WORKAROUNDS | 467 | #if ENABLE_WINDOWS_WORKAROUNDS |
281 | if (proc->control_pipe) | 468 | if (proc->control_pipe) |
282 | GNUNET_DISK_npipe_close (proc->control_pipe); | 469 | GNUNET_DISK_file_close (proc->control_pipe); |
283 | #endif | 470 | #endif |
284 | // FIXME NILS | 471 | // FIXME NILS |
285 | #ifdef WINDOWS | 472 | #ifdef WINDOWS |
286 | if (proc->handle != NULL) | 473 | if (proc->handle != NULL) |
287 | CloseHandle (proc->handle); | 474 | CloseHandle (proc->handle); |
288 | #endif | 475 | #endif |
476 | if (NULL != proc->childpipename) | ||
477 | { | ||
478 | cleanup_npipe (proc->childpipename); | ||
479 | GNUNET_free (proc->childpipename); | ||
480 | } | ||
289 | GNUNET_free (proc); | 481 | GNUNET_free (proc); |
290 | } | 482 | } |
291 | 483 | ||
@@ -417,11 +609,9 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, | |||
417 | } | 609 | } |
418 | } | 610 | } |
419 | #else | 611 | #else |
420 | #if DEBUG_OS | ||
421 | LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | 612 | LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, |
422 | "Priority management not availabe for this platform\n"); | 613 | "Priority management not availabe for this platform\n"); |
423 | #endif | 614 | #endif |
424 | #endif | ||
425 | return GNUNET_OK; | 615 | return GNUNET_OK; |
426 | } | 616 | } |
427 | 617 | ||
@@ -531,6 +721,7 @@ CreateCustomEnvTable (char **vars) | |||
531 | /** | 721 | /** |
532 | * Start a process. | 722 | * Start a process. |
533 | * | 723 | * |
724 | * @param pipe_control should a pipe be used to send signals to the child? | ||
534 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | 725 | * @param pipe_stdin pipe to use to send input to child process (or NULL) |
535 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | 726 | * @param pipe_stdout pipe to use to get output from child process (or NULL) |
536 | * @param filename name of the binary | 727 | * @param filename name of the binary |
@@ -538,32 +729,25 @@ CreateCustomEnvTable (char **vars) | |||
538 | * @return pointer to process structure of the new process, NULL on error | 729 | * @return pointer to process structure of the new process, NULL on error |
539 | */ | 730 | */ |
540 | struct GNUNET_OS_Process * | 731 | struct GNUNET_OS_Process * |
541 | GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | 732 | GNUNET_OS_start_process_vap (int pipe_control, |
733 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
542 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | 734 | struct GNUNET_DISK_PipeHandle *pipe_stdout, |
543 | const char *filename, | 735 | const char *filename, |
544 | char *const argv[]) | 736 | char *const argv[]) |
545 | { | 737 | { |
546 | #if ENABLE_WINDOWS_WORKAROUNDS | 738 | #ifndef MINGW |
547 | char *childpipename = NULL; | 739 | char *childpipename = NULL; |
548 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
549 | #endif | ||
550 | struct GNUNET_OS_Process *gnunet_proc = NULL; | 740 | struct GNUNET_OS_Process *gnunet_proc = NULL; |
551 | |||
552 | #ifndef MINGW | ||
553 | pid_t ret; | 741 | pid_t ret; |
554 | int fd_stdout_write; | 742 | int fd_stdout_write; |
555 | int fd_stdout_read; | 743 | int fd_stdout_read; |
556 | int fd_stdin_read; | 744 | int fd_stdin_read; |
557 | int fd_stdin_write; | 745 | int fd_stdin_write; |
558 | 746 | ||
559 | #if ENABLE_WINDOWS_WORKAROUNDS | 747 | if ( (GNUNET_YES == pipe_control) && |
560 | control_pipe = | 748 | (GNUNET_OK != |
561 | GNUNET_DISK_npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, | 749 | npipe_setup (&childpipename)) ) |
562 | GNUNET_DISK_PERM_USER_READ | | 750 | return NULL; |
563 | GNUNET_DISK_PERM_USER_WRITE); | ||
564 | if (control_pipe == NULL) | ||
565 | return NULL; | ||
566 | #endif | ||
567 | if (pipe_stdout != NULL) | 751 | if (pipe_stdout != NULL) |
568 | { | 752 | { |
569 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle | 753 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle |
@@ -585,34 +769,24 @@ GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
585 | } | 769 | } |
586 | 770 | ||
587 | ret = fork (); | 771 | ret = fork (); |
588 | if (ret != 0) | 772 | if (-1 == ret) |
589 | { | 773 | { |
590 | if (ret == -1) | 774 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); |
591 | { | 775 | GNUNET_free_non_null (childpipename); |
592 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); | 776 | return NULL; |
593 | #if ENABLE_WINDOWS_WORKAROUNDS | 777 | } |
594 | GNUNET_DISK_npipe_close (control_pipe); | 778 | if (0 != ret) |
595 | #endif | 779 | { |
596 | } | 780 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
597 | else | 781 | gnunet_proc->pid = ret; |
598 | { | 782 | gnunet_proc->childpipename = childpipename; |
599 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | ||
600 | gnunet_proc->pid = ret; | ||
601 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
602 | gnunet_proc->control_pipe = control_pipe; | ||
603 | #endif | ||
604 | } | ||
605 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
606 | GNUNET_free (childpipename); | ||
607 | #endif | ||
608 | return gnunet_proc; | 783 | return gnunet_proc; |
609 | } | 784 | } |
610 | 785 | if (NULL != childpipename) | |
611 | #if ENABLE_WINDOWS_WORKAROUNDS | 786 | { |
612 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); | 787 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); |
613 | GNUNET_free (childpipename); | 788 | GNUNET_free (childpipename); |
614 | #endif | 789 | } |
615 | |||
616 | if (pipe_stdout != NULL) | 790 | if (pipe_stdout != NULL) |
617 | { | 791 | { |
618 | GNUNET_break (0 == close (fd_stdout_read)); | 792 | GNUNET_break (0 == close (fd_stdout_read)); |
@@ -633,6 +807,8 @@ GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
633 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); | 807 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); |
634 | _exit (1); | 808 | _exit (1); |
635 | #else | 809 | #else |
810 | char *childpipename = NULL; | ||
811 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
636 | char *arg; | 812 | char *arg; |
637 | unsigned int cmdlen; | 813 | unsigned int cmdlen; |
638 | char *cmd, *idx; | 814 | char *cmd, *idx; |
@@ -749,26 +925,31 @@ GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
749 | &stdout_handle, sizeof (HANDLE)); | 925 | &stdout_handle, sizeof (HANDLE)); |
750 | start.hStdOutput = stdout_handle; | 926 | start.hStdOutput = stdout_handle; |
751 | } | 927 | } |
752 | 928 | if (GNUNET_YES == pipe_control) | |
753 | control_pipe = | ||
754 | GNUNET_DISK_npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, | ||
755 | GNUNET_DISK_PERM_USER_READ | | ||
756 | GNUNET_DISK_PERM_USER_WRITE); | ||
757 | if (control_pipe == NULL) | ||
758 | { | 929 | { |
759 | GNUNET_free (cmd); | 930 | control_pipe = |
760 | GNUNET_free (path); | 931 | npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, |
761 | return NULL; | 932 | GNUNET_DISK_PERM_USER_READ | |
933 | GNUNET_DISK_PERM_USER_WRITE); | ||
934 | if (control_pipe == NULL) | ||
935 | { | ||
936 | GNUNET_free (cmd); | ||
937 | GNUNET_free (path); | ||
938 | return NULL; | ||
939 | } | ||
940 | } | ||
941 | if (NULL != childpipename) | ||
942 | { | ||
943 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", | ||
944 | childpipename); | ||
945 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
946 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | ||
947 | our_env[2] = NULL; | ||
948 | } | ||
949 | else | ||
950 | { | ||
951 | our_env[0] = NULL; | ||
762 | } | 952 | } |
763 | |||
764 | #if DEBUG_OS | ||
765 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", | ||
766 | childpipename); | ||
767 | #endif | ||
768 | |||
769 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
770 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | ||
771 | our_env[2] = NULL; | ||
772 | env_block = CreateCustomEnvTable (our_env); | 953 | env_block = CreateCustomEnvTable (our_env); |
773 | GNUNET_free (our_env[0]); | 954 | GNUNET_free (our_env[0]); |
774 | GNUNET_free (our_env[1]); | 955 | GNUNET_free (our_env[1]); |
@@ -808,6 +989,7 @@ GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
808 | /** | 989 | /** |
809 | * Start a process. | 990 | * Start a process. |
810 | * | 991 | * |
992 | * @param pipe_control should a pipe be used to send signals to the child? | ||
811 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | 993 | * @param pipe_stdin pipe to use to send input to child process (or NULL) |
812 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | 994 | * @param pipe_stdout pipe to use to get output from child process (or NULL) |
813 | * @param filename name of the binary | 995 | * @param filename name of the binary |
@@ -815,7 +997,8 @@ GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
815 | * @return pointer to process structure of the new process, NULL on error | 997 | * @return pointer to process structure of the new process, NULL on error |
816 | */ | 998 | */ |
817 | struct GNUNET_OS_Process * | 999 | struct GNUNET_OS_Process * |
818 | GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, | 1000 | GNUNET_OS_start_process_va (int pipe_control, |
1001 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
819 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | 1002 | struct GNUNET_DISK_PipeHandle *pipe_stdout, |
820 | const char *filename, va_list va) | 1003 | const char *filename, va_list va) |
821 | { | 1004 | { |
@@ -835,7 +1018,8 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
835 | while (NULL != (argv[argc] = va_arg (ap, char *))) | 1018 | while (NULL != (argv[argc] = va_arg (ap, char *))) |
836 | argc++; | 1019 | argc++; |
837 | va_end (ap); | 1020 | va_end (ap); |
838 | ret = GNUNET_OS_start_process_vap (pipe_stdin, | 1021 | ret = GNUNET_OS_start_process_vap (pipe_control, |
1022 | pipe_stdin, | ||
839 | pipe_stdout, | 1023 | pipe_stdout, |
840 | filename, | 1024 | filename, |
841 | argv); | 1025 | argv); |
@@ -848,6 +1032,7 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
848 | /** | 1032 | /** |
849 | * Start a process. | 1033 | * Start a process. |
850 | * | 1034 | * |
1035 | * @param pipe_control should a pipe be used to send signals to the child? | ||
851 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | 1036 | * @param pipe_stdin pipe to use to send input to child process (or NULL) |
852 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | 1037 | * @param pipe_stdout pipe to use to get output from child process (or NULL) |
853 | * @param filename name of the binary | 1038 | * @param filename name of the binary |
@@ -857,7 +1042,8 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
857 | * | 1042 | * |
858 | */ | 1043 | */ |
859 | struct GNUNET_OS_Process * | 1044 | struct GNUNET_OS_Process * |
860 | GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | 1045 | GNUNET_OS_start_process (int pipe_control, |
1046 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
861 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | 1047 | struct GNUNET_DISK_PipeHandle *pipe_stdout, |
862 | const char *filename, ...) | 1048 | const char *filename, ...) |
863 | { | 1049 | { |
@@ -865,7 +1051,7 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
865 | va_list ap; | 1051 | va_list ap; |
866 | 1052 | ||
867 | va_start (ap, filename); | 1053 | va_start (ap, filename); |
868 | ret = GNUNET_OS_start_process_va (pipe_stdin, pipe_stdout, filename, ap); | 1054 | ret = GNUNET_OS_start_process_va (pipe_control, pipe_stdin, pipe_stdout, filename, ap); |
869 | va_end (ap); | 1055 | va_end (ap); |
870 | return ret; | 1056 | return ret; |
871 | } | 1057 | } |
@@ -874,6 +1060,7 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
874 | /** | 1060 | /** |
875 | * Start a process. | 1061 | * Start a process. |
876 | * | 1062 | * |
1063 | * @param pipe_control should a pipe be used to send signals to the child? | ||
877 | * @param lsocks array of listen sockets to dup systemd-style (or NULL); | 1064 | * @param lsocks array of listen sockets to dup systemd-style (or NULL); |
878 | * must be NULL on platforms where dup is not supported | 1065 | * must be NULL on platforms where dup is not supported |
879 | * @param filename name of the binary | 1066 | * @param filename name of the binary |
@@ -881,20 +1068,17 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
881 | * @return process ID of the new process, -1 on error | 1068 | * @return process ID of the new process, -1 on error |
882 | */ | 1069 | */ |
883 | struct GNUNET_OS_Process * | 1070 | struct GNUNET_OS_Process * |
884 | GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | 1071 | GNUNET_OS_start_process_v (int pipe_control, |
1072 | const SOCKTYPE *lsocks, | ||
885 | const char *filename, | 1073 | const char *filename, |
886 | char *const argv[]) | 1074 | char *const argv[]) |
887 | { | 1075 | { |
888 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
889 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
890 | char *childpipename = NULL; | ||
891 | #endif | ||
892 | |||
893 | #ifndef MINGW | 1076 | #ifndef MINGW |
894 | pid_t ret; | 1077 | pid_t ret; |
895 | char lpid[16]; | 1078 | char lpid[16]; |
896 | char fds[16]; | 1079 | char fds[16]; |
897 | struct GNUNET_OS_Process *gnunet_proc = NULL; | 1080 | struct GNUNET_OS_Process *gnunet_proc = NULL; |
1081 | char *childpipename = NULL; | ||
898 | int i; | 1082 | int i; |
899 | int j; | 1083 | int j; |
900 | int k; | 1084 | int k; |
@@ -903,15 +1087,9 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
903 | int *lscp; | 1087 | int *lscp; |
904 | unsigned int ls; | 1088 | unsigned int ls; |
905 | 1089 | ||
906 | #if ENABLE_WINDOWS_WORKAROUNDS | 1090 | if ( (GNUNET_YES == pipe_control) && |
907 | control_pipe = | 1091 | (GNUNET_OK != npipe_setup (&childpipename)) ) |
908 | GNUNET_DISK_npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, | 1092 | return NULL; |
909 | GNUNET_DISK_PERM_USER_READ | | ||
910 | GNUNET_DISK_PERM_USER_WRITE); | ||
911 | if (control_pipe == NULL) | ||
912 | return NULL; | ||
913 | #endif | ||
914 | |||
915 | lscp = NULL; | 1093 | lscp = NULL; |
916 | ls = 0; | 1094 | ls = 0; |
917 | if (lsocks != NULL) | 1095 | if (lsocks != NULL) |
@@ -922,36 +1100,26 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
922 | GNUNET_array_append (lscp, ls, -1); | 1100 | GNUNET_array_append (lscp, ls, -1); |
923 | } | 1101 | } |
924 | ret = fork (); | 1102 | ret = fork (); |
925 | if (ret != 0) | 1103 | if (-1 == ret) |
926 | { | 1104 | { |
927 | if (ret == -1) | 1105 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); |
928 | { | 1106 | GNUNET_free_non_null (childpipename); |
929 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); | 1107 | GNUNET_array_grow (lscp, ls, 0); |
930 | #if ENABLE_WINDOWS_WORKAROUNDS | 1108 | return NULL; |
931 | GNUNET_DISK_npipe_close (control_pipe); | 1109 | } |
932 | #endif | 1110 | if (0 != ret) |
933 | } | 1111 | { |
934 | else | 1112 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
935 | { | 1113 | gnunet_proc->pid = ret; |
936 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 1114 | gnunet_proc->childpipename = childpipename; |
937 | gnunet_proc->pid = ret; | ||
938 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
939 | gnunet_proc->control_pipe = control_pipe; | ||
940 | |||
941 | #endif | ||
942 | } | ||
943 | GNUNET_array_grow (lscp, ls, 0); | 1115 | GNUNET_array_grow (lscp, ls, 0); |
944 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
945 | GNUNET_free (childpipename); | ||
946 | #endif | ||
947 | return gnunet_proc; | 1116 | return gnunet_proc; |
948 | } | 1117 | } |
949 | 1118 | if (NULL != childpipename) | |
950 | #if ENABLE_WINDOWS_WORKAROUNDS | 1119 | { |
951 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); | 1120 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); |
952 | GNUNET_free (childpipename); | 1121 | GNUNET_free (childpipename); |
953 | #endif | 1122 | } |
954 | |||
955 | if (lscp != NULL) | 1123 | if (lscp != NULL) |
956 | { | 1124 | { |
957 | /* read systemd documentation... */ | 1125 | /* read systemd documentation... */ |
@@ -999,6 +1167,8 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
999 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); | 1167 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); |
1000 | _exit (1); | 1168 | _exit (1); |
1001 | #else | 1169 | #else |
1170 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
1171 | char *childpipename = NULL; | ||
1002 | char **arg, **non_const_argv; | 1172 | char **arg, **non_const_argv; |
1003 | unsigned int cmdlen; | 1173 | unsigned int cmdlen; |
1004 | char *cmd, *idx; | 1174 | char *cmd, *idx; |
@@ -1006,9 +1176,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1006 | PROCESS_INFORMATION proc; | 1176 | PROCESS_INFORMATION proc; |
1007 | int argcount = 0; | 1177 | int argcount = 0; |
1008 | struct GNUNET_OS_Process *gnunet_proc = NULL; | 1178 | struct GNUNET_OS_Process *gnunet_proc = NULL; |
1009 | |||
1010 | char path[MAX_PATH + 1]; | 1179 | char path[MAX_PATH + 1]; |
1011 | |||
1012 | char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; | 1180 | char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; |
1013 | char *env_block = NULL; | 1181 | char *env_block = NULL; |
1014 | char *pathbuf; | 1182 | char *pathbuf; |
@@ -1023,7 +1191,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1023 | HANDLE lsocks_read; | 1191 | HANDLE lsocks_read; |
1024 | HANDLE lsocks_write; | 1192 | HANDLE lsocks_write; |
1025 | wchar_t wpath[MAX_PATH + 1], wcmd[32768]; | 1193 | wchar_t wpath[MAX_PATH + 1], wcmd[32768]; |
1026 | 1194 | int env_off; | |
1027 | int fail; | 1195 | int fail; |
1028 | 1196 | ||
1029 | /* Search in prefix dir (hopefully - the directory from which | 1197 | /* Search in prefix dir (hopefully - the directory from which |
@@ -1130,15 +1298,18 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1130 | memset (&start, 0, sizeof (start)); | 1298 | memset (&start, 0, sizeof (start)); |
1131 | start.cb = sizeof (start); | 1299 | start.cb = sizeof (start); |
1132 | 1300 | ||
1133 | control_pipe = | 1301 | if (GNUNET_YES == pipe_control) |
1134 | GNUNET_DISK_npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, | ||
1135 | GNUNET_DISK_PERM_USER_READ | | ||
1136 | GNUNET_DISK_PERM_USER_WRITE); | ||
1137 | if (control_pipe == NULL) | ||
1138 | { | 1302 | { |
1139 | GNUNET_free (cmd); | 1303 | control_pipe = |
1140 | GNUNET_free (path); | 1304 | npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, |
1141 | return NULL; | 1305 | GNUNET_DISK_PERM_USER_READ | |
1306 | GNUNET_DISK_PERM_USER_WRITE); | ||
1307 | if (control_pipe == NULL) | ||
1308 | { | ||
1309 | GNUNET_free (cmd); | ||
1310 | GNUNET_free (path); | ||
1311 | return NULL; | ||
1312 | } | ||
1142 | } | 1313 | } |
1143 | if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) | 1314 | if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) |
1144 | { | 1315 | { |
@@ -1160,29 +1331,25 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1160 | &lsocks_read, sizeof (HANDLE)); | 1331 | &lsocks_read, sizeof (HANDLE)); |
1161 | } | 1332 | } |
1162 | 1333 | ||
1163 | #if DEBUG_OS | 1334 | env_off = 0; |
1164 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", | 1335 | if (NULL != childpipename) |
1165 | childpipename); | 1336 | { |
1166 | #endif | 1337 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", |
1167 | 1338 | childpipename); | |
1168 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | 1339 | GNUNET_asprintf (&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE); |
1169 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | 1340 | GNUNET_asprintf (&our_env[env_off++], "%s", childpipename); |
1170 | GNUNET_free (childpipename); | 1341 | GNUNET_free (childpipename); |
1171 | if (lsocks == NULL || lsocks[0] == INVALID_SOCKET) | 1342 | } |
1172 | our_env[2] = NULL; | 1343 | if ( (lsocks != NULL) && (lsocks[0] != INVALID_SOCKET)) |
1173 | else | ||
1174 | { | 1344 | { |
1175 | /*This will tell the child that we're going to send lsocks over the pipe*/ | 1345 | /*This will tell the child that we're going to send lsocks over the pipe*/ |
1176 | GNUNET_asprintf (&our_env[2], "%s=", "GNUNET_OS_READ_LSOCKS"); | 1346 | GNUNET_asprintf (&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS"); |
1177 | GNUNET_asprintf (&our_env[3], "%lu", lsocks_read); | 1347 | GNUNET_asprintf (&our_env[env_off++], "%lu", lsocks_read); |
1178 | our_env[4] = NULL; | ||
1179 | } | 1348 | } |
1349 | our_env[env_off++] = NULL; | ||
1180 | env_block = CreateCustomEnvTable (our_env); | 1350 | env_block = CreateCustomEnvTable (our_env); |
1181 | GNUNET_free_non_null (our_env[0]); | 1351 | while (0 > env_off) |
1182 | GNUNET_free_non_null (our_env[1]); | 1352 | GNUNET_free_non_null (our_env[--env_off]); |
1183 | GNUNET_free_non_null (our_env[2]); | ||
1184 | GNUNET_free_non_null (our_env[3]); | ||
1185 | |||
1186 | if (ERROR_SUCCESS != plibc_conv_to_win_pathwconv(path, wpath) | 1353 | if (ERROR_SUCCESS != plibc_conv_to_win_pathwconv(path, wpath) |
1187 | || ERROR_SUCCESS != plibc_conv_to_win_pathwconv(cmd, wcmd) | 1354 | || ERROR_SUCCESS != plibc_conv_to_win_pathwconv(cmd, wcmd) |
1188 | || !CreateProcessW | 1355 | || !CreateProcessW |
@@ -1191,8 +1358,9 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1191 | { | 1358 | { |
1192 | SetErrnoFromWinError (GetLastError ()); | 1359 | SetErrnoFromWinError (GetLastError ()); |
1193 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); | 1360 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); |
1194 | GNUNET_DISK_npipe_close (control_pipe); | 1361 | if (NULL != control_pipe) |
1195 | if (lsocks != NULL) | 1362 | GNUNET_DISK_file_close (control_pipe); |
1363 | if (NULL != lsocks) | ||
1196 | GNUNET_DISK_pipe_close (lsocks_pipe); | 1364 | GNUNET_DISK_pipe_close (lsocks_pipe); |
1197 | GNUNET_free (env_block); | 1365 | GNUNET_free (env_block); |
1198 | GNUNET_free (cmd); | 1366 | GNUNET_free (cmd); |
@@ -1286,11 +1454,11 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, | |||
1286 | */ | 1454 | */ |
1287 | TerminateProcess (gnunet_proc->handle, 0); | 1455 | TerminateProcess (gnunet_proc->handle, 0); |
1288 | CloseHandle (gnunet_proc->handle); | 1456 | CloseHandle (gnunet_proc->handle); |
1289 | GNUNET_DISK_npipe_close (gnunet_proc->control_pipe); | 1457 | if (NULL != gnunet_proc->control_pipe) |
1458 | GNUNET_DISK_file_close (gnunet_proc->control_pipe); | ||
1290 | GNUNET_free (gnunet_proc); | 1459 | GNUNET_free (gnunet_proc); |
1291 | return NULL; | 1460 | return NULL; |
1292 | } | 1461 | } |
1293 | |||
1294 | return gnunet_proc; | 1462 | return gnunet_proc; |
1295 | #endif | 1463 | #endif |
1296 | } | 1464 | } |
@@ -1599,7 +1767,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, | |||
1599 | if (NULL == opipe) | 1767 | if (NULL == opipe) |
1600 | return NULL; | 1768 | return NULL; |
1601 | va_start (ap, binary); | 1769 | va_start (ap, binary); |
1602 | eip = GNUNET_OS_start_process_va (NULL, opipe, binary, ap); | 1770 | eip = GNUNET_OS_start_process_va (GNUNET_NO, NULL, opipe, binary, ap); |
1603 | va_end (ap); | 1771 | va_end (ap); |
1604 | if (NULL == eip) | 1772 | if (NULL == eip) |
1605 | { | 1773 | { |