summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-27 11:00:10 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-27 11:00:10 +0000
commit0238db34853380280ccf164918ebbb28260f4629 (patch)
tree2c47ddbbfa27e7a0479d5c12e78d77342780a4bd /src/util
parentdc3ae8f36ec69ca2a96a93feda501682ff168320 (diff)
downloadgnunet-0238db34853380280ccf164918ebbb28260f4629.tar.gz
gnunet-0238db34853380280ccf164918ebbb28260f4629.zip
enabling use of pipes for signal communication also on UNIX to enable future integration with Java services
Diffstat (limited to 'src/util')
-rw-r--r--src/util/crypto_random.c7
-rw-r--r--src/util/disk.c210
-rw-r--r--src/util/helper.c3
-rw-r--r--src/util/os_priority.c688
-rw-r--r--src/util/scheduler.c2
-rw-r--r--src/util/test_common_logging_runtime_loglevels.c2
-rw-r--r--src/util/test_os_start_process.c2
-rw-r--r--src/util/test_resolver_api.c2
-rw-r--r--src/util/test_strings.c2
9 files changed, 440 insertions, 478 deletions
diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c
index 8f9ba80f6..25226a3b4 100644
--- a/src/util/crypto_random.c
+++ b/src/util/crypto_random.c
@@ -280,9 +280,10 @@ entropy_generator (void *cls, const char *what, int printchar, int current,
280 LOG (GNUNET_ERROR_TYPE_INFO, _("Starting `%s' process to generate entropy\n"), 280 LOG (GNUNET_ERROR_TYPE_INFO, _("Starting `%s' process to generate entropy\n"),
281 "find"); 281 "find");
282 genproc = 282 genproc =
283 GNUNET_OS_start_process (NULL, NULL, "sh", "sh", "-c", 283 GNUNET_OS_start_process (GNUNET_NO,
284 "exec find / -mount -type f -exec cp {} /dev/null \\; 2>/dev/null", 284 NULL, NULL, "sh", "sh", "-c",
285 NULL); 285 "exec find / -mount -type f -exec cp {} /dev/null \\; 2>/dev/null",
286 NULL);
286} 287}
287 288
288 289
diff --git a/src/util/disk.c b/src/util/disk.c
index e4d9f172a..e4d5ed32b 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -1610,7 +1610,7 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags,
1610 mode = translate_unix_perms (perm); 1610 mode = translate_unix_perms (perm);
1611 } 1611 }
1612 1612
1613 fd = open (expfn, oflags | O_LARGEFILE, mode); 1613 fd = open (expfn, oflags | O_LARGEFILE | O_NONBLOCK, mode);
1614 if (fd == -1) 1614 if (fd == -1)
1615 { 1615 {
1616 if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) 1616 if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
@@ -2455,214 +2455,6 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
2455 2455
2456 2456
2457/** 2457/**
2458 * Creates a named pipe/FIFO and opens it
2459 * @param fn pointer to the name of the named pipe or to NULL
2460 * @param flags open flags
2461 * @param perm access permissions
2462 * @return pipe handle on success, NULL on error
2463 */
2464struct GNUNET_DISK_FileHandle *
2465GNUNET_DISK_npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags,
2466 enum GNUNET_DISK_AccessPermissions perm)
2467{
2468#ifdef MINGW
2469 struct GNUNET_DISK_FileHandle *ret;
2470 HANDLE h = NULL;
2471 DWORD openMode;
2472 char *name;
2473
2474 openMode = 0;
2475 if (flags & GNUNET_DISK_OPEN_READWRITE)
2476 openMode = PIPE_ACCESS_DUPLEX;
2477 else if (flags & GNUNET_DISK_OPEN_READ)
2478 openMode = PIPE_ACCESS_INBOUND;
2479 else if (flags & GNUNET_DISK_OPEN_WRITE)
2480 openMode = PIPE_ACCESS_OUTBOUND;
2481
2482 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
2483 openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
2484
2485 while (h == NULL)
2486 {
2487 DWORD error_code;
2488
2489 name = NULL;
2490 if (*fn != NULL)
2491 {
2492 GNUNET_asprintf (&name, "\\\\.\\pipe\\%.246s", fn);
2493#if DEBUG_NPIPE
2494 LOG (GNUNET_ERROR_TYPE_DEBUG,
2495 "Trying to create an instance of named pipe `%s'\n", name);
2496#endif
2497 /* 1) This might work just fine with UTF-8 strings as it is.
2498 * 2) This is only used by GNUnet itself, and only with latin names.
2499 */
2500 h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED,
2501 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
2502 NULL);
2503 }
2504 else
2505 {
2506 GNUNET_asprintf (fn, "\\\\.\\pipe\\gnunet-%llu",
2507 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
2508 UINT64_MAX));
2509#if DEBUG_NPIPE
2510 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n",
2511 *fn);
2512#endif
2513 h = CreateNamedPipe (*fn,
2514 openMode | FILE_FLAG_OVERLAPPED |
2515 FILE_FLAG_FIRST_PIPE_INSTANCE,
2516 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
2517 NULL);
2518 }
2519 error_code = GetLastError ();
2520 if (name)
2521 GNUNET_free (name);
2522 /* don't re-set name to NULL yet */
2523 if (h == INVALID_HANDLE_VALUE)
2524 {
2525 SetErrnoFromWinError (error_code);
2526#if DEBUG_NPIPE
2527 LOG (GNUNET_ERROR_TYPE_DEBUG,
2528 "Pipe creation have failed because of %d, errno is %d\n", error_code,
2529 errno);
2530#endif
2531 if (name == NULL)
2532 {
2533#if DEBUG_NPIPE
2534 LOG (GNUNET_ERROR_TYPE_DEBUG,
2535 "Pipe was to be unique, considering re-creation\n");
2536#endif
2537 GNUNET_free (*fn);
2538 *fn = NULL;
2539 if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY)
2540 {
2541 return NULL;
2542 }
2543#if DEBUG_NPIPE
2544 LOG (GNUNET_ERROR_TYPE_DEBUG,
2545 "Pipe name was not unique, trying again\n");
2546#endif
2547 h = NULL;
2548 }
2549 else
2550 return NULL;
2551 }
2552 }
2553 errno = 0;
2554
2555 ret = GNUNET_malloc (sizeof (*ret));
2556 ret->h = h;
2557 ret->type = GNUNET_PIPE;
2558
2559 ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
2560 ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
2561
2562 ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2563 ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2564
2565 return ret;
2566#else
2567 if (*fn == NULL)
2568 {
2569 char dir[] = "/tmp/gnunet-pipe-XXXXXX";
2570
2571 if (mkdtemp (dir) == NULL)
2572 {
2573 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "mkdtemp");
2574 return NULL;
2575 }
2576 GNUNET_asprintf (fn, "%s/child-control", dir);
2577 }
2578
2579 if (mkfifo (*fn, translate_unix_perms (perm)) == -1)
2580 {
2581 if ((errno != EEXIST) || (0 != (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)))
2582 return NULL;
2583 }
2584
2585 flags = flags & (~GNUNET_DISK_OPEN_FAILIFEXISTS);
2586 return GNUNET_DISK_file_open (*fn, flags, perm);
2587#endif
2588}
2589
2590
2591/**
2592 * Opens already existing named pipe/FIFO
2593 *
2594 * @param fn name of an existing named pipe
2595 * @param flags open flags
2596 * @param perm access permissions
2597 * @return pipe handle on success, NULL on error
2598 */
2599struct GNUNET_DISK_FileHandle *
2600GNUNET_DISK_npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags,
2601 enum GNUNET_DISK_AccessPermissions perm)
2602{
2603#ifdef MINGW
2604 struct GNUNET_DISK_FileHandle *ret;
2605 HANDLE h;
2606 DWORD openMode;
2607
2608 openMode = 0;
2609 if (flags & GNUNET_DISK_OPEN_READWRITE)
2610 openMode = GENERIC_WRITE | GENERIC_READ;
2611 else if (flags & GNUNET_DISK_OPEN_READ)
2612 openMode = GENERIC_READ;
2613 else if (flags & GNUNET_DISK_OPEN_WRITE)
2614 openMode = GENERIC_WRITE;
2615
2616 h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING,
2617 FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
2618 if (h == INVALID_HANDLE_VALUE)
2619 {
2620 SetErrnoFromWinError (GetLastError ());
2621 return NULL;
2622 }
2623
2624 ret = GNUNET_malloc (sizeof (*ret));
2625 ret->h = h;
2626 ret->type = GNUNET_PIPE;
2627 ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
2628 ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
2629 ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2630 ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2631
2632 return ret;
2633#else
2634 flags = flags & (~GNUNET_DISK_OPEN_FAILIFEXISTS);
2635 return GNUNET_DISK_file_open (fn, flags, perm);
2636#endif
2637}
2638
2639
2640/**
2641 * Closes a named pipe/FIFO
2642 * @param pipe named pipe
2643 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
2644 */
2645int
2646GNUNET_DISK_npipe_close (struct GNUNET_DISK_FileHandle *pipe)
2647{
2648#ifndef MINGW
2649 return close (pipe->fd) == 0 ? GNUNET_OK : GNUNET_SYSERR;
2650#else
2651 BOOL ret;
2652
2653 ret = CloseHandle (pipe->h);
2654 if (!ret)
2655 {
2656 SetErrnoFromWinError (GetLastError ());
2657 return GNUNET_SYSERR;
2658 }
2659 else
2660 return GNUNET_OK;
2661#endif
2662}
2663
2664
2665/**
2666 * Get the handle to a particular pipe end 2458 * Get the handle to a particular pipe end
2667 * 2459 *
2668 * @param p pipe 2460 * @param p pipe
diff --git a/src/util/helper.c b/src/util/helper.c
index e5d336e2f..43ec23a88 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -306,7 +306,8 @@ start_helper (struct GNUNET_HELPER_Handle *h)
306 h->fh_to_helper = 306 h->fh_to_helper =
307 GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE); 307 GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE);
308 h->helper_proc = 308 h->helper_proc =
309 GNUNET_OS_start_process_vap (h->helper_in, h->helper_out, 309 GNUNET_OS_start_process_vap (GNUNET_NO,
310 h->helper_in, h->helper_out,
310 h->binary_name, 311 h->binary_name,
311 h->binary_argv); 312 h->binary_argv);
312 if (NULL == h->helper_proc) 313 if (NULL == h->helper_proc)
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
44struct GNUNET_OS_Process 42struct 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 */
54static struct GNUNET_OS_Process current_process; 71static 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 */
84static struct GNUNET_DISK_FileHandle *
85npipe_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 */
182static struct GNUNET_DISK_FileHandle *
183npipe_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 */
225static void
226cleanup_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 */
248static int
249npipe_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 */
277static struct GNUNET_DISK_FileHandle *
278npipe_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
64parent_control_handler (void *cls, 295parent_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 */
106void 334void
107GNUNET_OS_install_parent_control_handler (void *cls, 335GNUNET_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 */
163int 397int
164GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) 398GNUNET_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 */
540struct GNUNET_OS_Process * 731struct GNUNET_OS_Process *
541GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin, 732GNUNET_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 */
817struct GNUNET_OS_Process * 999struct GNUNET_OS_Process *
818GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, 1000GNUNET_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 */
859struct GNUNET_OS_Process * 1044struct GNUNET_OS_Process *
860GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, 1045GNUNET_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 */
883struct GNUNET_OS_Process * 1070struct GNUNET_OS_Process *
884GNUNET_OS_start_process_v (const SOCKTYPE *lsocks, 1071GNUNET_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 {
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index f1cecd4ef..c54672f5f 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -818,13 +818,11 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
818 current_lifeness = GNUNET_YES; 818 current_lifeness = GNUNET_YES;
819 GNUNET_SCHEDULER_add_continuation (task, task_cls, 819 GNUNET_SCHEDULER_add_continuation (task, task_cls,
820 GNUNET_SCHEDULER_REASON_STARTUP); 820 GNUNET_SCHEDULER_REASON_STARTUP);
821#if ENABLE_WINDOWS_WORKAROUNDS
822 active_task = (void *) (long) -1; /* force passing of sanity check */ 821 active_task = (void *) (long) -1; /* force passing of sanity check */
823 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, 822 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
824 &GNUNET_OS_install_parent_control_handler, 823 &GNUNET_OS_install_parent_control_handler,
825 NULL); 824 NULL);
826 active_task = NULL; 825 active_task = NULL;
827#endif
828 last_tr = 0; 826 last_tr = 0;
829 busy_wait_warning = 0; 827 busy_wait_warning = 0;
830 while (GNUNET_OK == check_lifeness ()) 828 while (GNUNET_OK == check_lifeness ())
diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c
index b6b9d6178..cdf1f660d 100644
--- a/src/util/test_common_logging_runtime_loglevels.c
+++ b/src/util/test_common_logging_runtime_loglevels.c
@@ -314,7 +314,7 @@ runone ()
314 break; 314 break;
315 } 315 }
316 316
317 proc = GNUNET_OS_start_process (NULL, pipe_stdout, 317 proc = GNUNET_OS_start_process (GNUNET_NO, NULL, pipe_stdout,
318#if MINGW 318#if MINGW
319 "test_common_logging_dummy", 319 "test_common_logging_dummy",
320#else 320#else
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c
index 178a1d9ef..54638c12f 100644
--- a/src/util/test_os_start_process.c
+++ b/src/util/test_os_start_process.c
@@ -126,7 +126,7 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
126 } 126 }
127 127
128 proc = 128 proc =
129 GNUNET_OS_start_process (hello_pipe_stdin, hello_pipe_stdout, fn, 129 GNUNET_OS_start_process (GNUNET_NO, hello_pipe_stdin, hello_pipe_stdout, fn,
130 "test_gnunet_echo_hello", "-", NULL); 130 "test_gnunet_echo_hello", "-", NULL);
131 GNUNET_free (fn); 131 GNUNET_free (fn);
132 132
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index 4ad5a2cf5..67d5f4640 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -393,7 +393,7 @@ check ()
393 pfx = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); 393 pfx = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
394 GNUNET_asprintf (&fn, "%s%cgnunet-service-resolver", pfx, DIR_SEPARATOR); 394 GNUNET_asprintf (&fn, "%s%cgnunet-service-resolver", pfx, DIR_SEPARATOR);
395 GNUNET_free (pfx); 395 GNUNET_free (pfx);
396 proc = GNUNET_OS_start_process (NULL, NULL, fn, "gnunet-service-resolver", 396 proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, fn, "gnunet-service-resolver",
397#if VERBOSE 397#if VERBOSE
398 "-L", "DEBUG", 398 "-L", "DEBUG",
399#endif 399#endif
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index 88de0b81b..570776a81 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -97,7 +97,9 @@ check ()
97 GNUNET_free (r); 97 GNUNET_free (r);
98 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII"); 98 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII");
99 WANT ("TEST", b); 99 WANT ("TEST", b);
100 GNUNET_log_skip (2, GNUNET_NO);
100 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "unknown"); 101 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "unknown");
102 GNUNET_log_skip (0, GNUNET_YES);
101 WANT ("TEST", b); 103 WANT ("TEST", b);
102 return 0; 104 return 0;
103} 105}