aboutsummaryrefslogtreecommitdiff
path: root/src/util/os_priority.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/os_priority.c')
-rw-r--r--src/util/os_priority.c190
1 files changed, 131 insertions, 59 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index 8dfec6c5e..2a6ea8321 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -65,49 +65,68 @@ struct GNUNET_OS_Process
65 */ 65 */
66static struct GNUNET_OS_Process current_process; 66static struct GNUNET_OS_Process current_process;
67 67
68/**
69 * Handle for the #parent_control_handler() Task.
70 */
71static struct GNUNET_SCHEDULER_Task *pch;
72
73
74/**
75 * This handler is called on shutdown to remove the #pch.
76 *
77 * @param cls the `struct GNUNET_DISK_FileHandle` of the control pipe
78 */
79static void
80shutdown_pch (void *cls)
81{
82 struct GNUNET_DISK_FileHandle *control_pipe = cls;
83
84 GNUNET_SCHEDULER_cancel (pch);
85 pch = NULL;
86 GNUNET_DISK_file_close (control_pipe);
87 control_pipe = NULL;
88}
89
68 90
69/** 91/**
70 * This handler is called when there are control data to be read on the pipe 92 * This handler is called when there are control data to be read on the pipe
71 * 93 *
72 * @param cls the 'struct GNUNET_DISK_FileHandle' of the control pipe 94 * @param cls the `struct GNUNET_DISK_FileHandle` of the control pipe
73 */ 95 */
74static void 96static void
75parent_control_handler (void *cls) 97parent_control_handler (void *cls)
76{ 98{
77 struct GNUNET_DISK_FileHandle *control_pipe = cls; 99 struct GNUNET_DISK_FileHandle *control_pipe = cls;
78 const struct GNUNET_SCHEDULER_TaskContext *tc;
79 char sig; 100 char sig;
80 char *pipe_fd; 101 char *pipe_fd;
81 ssize_t ret; 102 ssize_t ret;
82 103
83 tc = GNUNET_SCHEDULER_get_task_context (); 104 pch = NULL;
84 LOG (GNUNET_ERROR_TYPE_DEBUG, 105 ret = GNUNET_DISK_file_read (control_pipe,
85 "`%s' invoked because of %d\n", __FUNCTION__, 106 &sig,
86 tc->reason); 107 sizeof (sig));
87 if (0 != (tc->reason &
88 (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT)))
89 {
90 GNUNET_DISK_file_close (control_pipe);
91 control_pipe = NULL;
92 return;
93 }
94 ret = GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig));
95 if (sizeof (sig) != ret) 108 if (sizeof (sig) != ret)
96 { 109 {
97 if (-1 == ret) 110 if (-1 == ret)
98 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); 111 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
99 LOG (GNUNET_ERROR_TYPE_DEBUG, "Closing control pipe\n"); 112 "GNUNET_DISK_file_read");
113 LOG (GNUNET_ERROR_TYPE_DEBUG,
114 "Closing control pipe\n");
100 GNUNET_DISK_file_close (control_pipe); 115 GNUNET_DISK_file_close (control_pipe);
101 control_pipe = NULL; 116 control_pipe = NULL;
102 return; 117 return;
103 } 118 }
104 pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE); 119 pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE);
105 GNUNET_assert ( (NULL == pipe_fd) || (strlen (pipe_fd) <= 0) ); 120 GNUNET_assert ( (NULL == pipe_fd) ||
121 (strlen (pipe_fd) <= 0) );
106 LOG (GNUNET_ERROR_TYPE_DEBUG, 122 LOG (GNUNET_ERROR_TYPE_DEBUG,
107 "Got control code %d from parent via pipe %s\n", sig, pipe_fd); 123 "Got control code %d from parent via pipe %s\n",
108 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 124 sig,
109 control_pipe, &parent_control_handler, 125 pipe_fd);
110 control_pipe); 126 pch = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
127 control_pipe,
128 &parent_control_handler,
129 control_pipe);
111 GNUNET_SIGNAL_raise ((int) sig); 130 GNUNET_SIGNAL_raise ((int) sig);
112} 131}
113 132
@@ -115,7 +134,7 @@ parent_control_handler (void *cls)
115/** 134/**
116 * Task that connects this process to its parent via pipe; 135 * Task that connects this process to its parent via pipe;
117 * essentially, the parent control handler will read signal numbers 136 * essentially, the parent control handler will read signal numbers
118 * from the 'GNUNET_OS_CONTROL_PIPE' (as given in an environment 137 * from the #GNUNET_OS_CONTROL_PIPE (as given in an environment
119 * variable) and raise those signals. 138 * variable) and raise those signals.
120 * 139 *
121 * @param cls closure (unused) 140 * @param cls closure (unused)
@@ -128,6 +147,12 @@ GNUNET_OS_install_parent_control_handler (void *cls)
128 struct GNUNET_DISK_FileHandle *control_pipe; 147 struct GNUNET_DISK_FileHandle *control_pipe;
129 uint64_t pipe_fd; 148 uint64_t pipe_fd;
130 149
150 if (NULL != pch)
151 {
152 /* already done, we've been called twice... */
153 GNUNET_break (0);
154 return;
155 }
131 env_buf = getenv (GNUNET_OS_CONTROL_PIPE); 156 env_buf = getenv (GNUNET_OS_CONTROL_PIPE);
132 if ( (NULL == env_buf) || (strlen (env_buf) <= 0) ) 157 if ( (NULL == env_buf) || (strlen (env_buf) <= 0) )
133 { 158 {
@@ -141,7 +166,9 @@ GNUNET_OS_install_parent_control_handler (void *cls)
141 pipe_fd = strtoull (env_buf, &env_buf_end, 16); 166 pipe_fd = strtoull (env_buf, &env_buf_end, 16);
142 if ((0 != errno) || (env_buf == env_buf_end)) 167 if ((0 != errno) || (env_buf == env_buf_end))
143 { 168 {
144 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "strtoull", env_buf); 169 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
170 "strtoull",
171 env_buf);
145 putenv (GNUNET_OS_CONTROL_PIPE "="); 172 putenv (GNUNET_OS_CONTROL_PIPE "=");
146 return; 173 return;
147 } 174 }
@@ -153,7 +180,8 @@ GNUNET_OS_install_parent_control_handler (void *cls)
153#endif 180#endif
154 { 181 {
155 LOG (GNUNET_ERROR_TYPE_ERROR, 182 LOG (GNUNET_ERROR_TYPE_ERROR,
156 "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n", env_buf); 183 "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n",
184 env_buf);
157 putenv (GNUNET_OS_CONTROL_PIPE "="); 185 putenv (GNUNET_OS_CONTROL_PIPE "=");
158 return; 186 return;
159 } 187 }
@@ -164,14 +192,21 @@ GNUNET_OS_install_parent_control_handler (void *cls)
164#endif 192#endif
165 if (NULL == control_pipe) 193 if (NULL == control_pipe)
166 { 194 {
167 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf); 195 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
196 "open",
197 env_buf);
168 putenv (GNUNET_OS_CONTROL_PIPE "="); 198 putenv (GNUNET_OS_CONTROL_PIPE "=");
169 return; 199 return;
170 } 200 }
171 LOG (GNUNET_ERROR_TYPE_DEBUG, 201 LOG (GNUNET_ERROR_TYPE_DEBUG,
172 "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); 202 "Adding parent control handler pipe `%s' to the scheduler\n",
173 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, 203 env_buf);
174 &parent_control_handler, control_pipe); 204 pch = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
205 control_pipe,
206 &parent_control_handler,
207 control_pipe);
208 GNUNET_SCHEDULER_add_shutdown (&shutdown_pch,
209 control_pipe);
175 putenv (GNUNET_OS_CONTROL_PIPE "="); 210 putenv (GNUNET_OS_CONTROL_PIPE "=");
176} 211}
177 212
@@ -179,8 +214,8 @@ GNUNET_OS_install_parent_control_handler (void *cls)
179/** 214/**
180 * Get process structure for current process 215 * Get process structure for current process
181 * 216 *
182 * The pointer it returns points to static memory location and must not be 217 * The pointer it returns points to static memory location and must
183 * deallocated/closed 218 * not be deallocated/closed.
184 * 219 *
185 * @return pointer to the process sturcutre for this process 220 * @return pointer to the process sturcutre for this process
186 */ 221 */
@@ -205,7 +240,8 @@ GNUNET_OS_process_current ()
205 * @return 0 on success, -1 on error 240 * @return 0 on success, -1 on error
206 */ 241 */
207int 242int
208GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) 243GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc,
244 int sig)
209{ 245{
210 int ret; 246 int ret;
211 char csig; 247 char csig;
@@ -213,8 +249,13 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
213 csig = (char) sig; 249 csig = (char) sig;
214 if (NULL != proc->control_pipe) 250 if (NULL != proc->control_pipe)
215 { 251 {
216 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via pipe\n", sig, proc->pid); 252 LOG (GNUNET_ERROR_TYPE_DEBUG,
217 ret = GNUNET_DISK_file_write (proc->control_pipe, &csig, sizeof (csig)); 253 "Sending signal %d to pid: %u via pipe\n",
254 sig,
255 proc->pid);
256 ret = GNUNET_DISK_file_write (proc->control_pipe,
257 &csig,
258 sizeof (csig));
218 if (sizeof (csig) == ret) 259 if (sizeof (csig) == ret)
219 return 0; 260 return 0;
220 } 261 }
@@ -237,14 +278,17 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
237 if (0 != GetExitCodeProcess (proc->handle, &exitcode)) 278 if (0 != GetExitCodeProcess (proc->handle, &exitcode))
238 must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO; 279 must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO;
239 if (GNUNET_YES == must_kill) 280 if (GNUNET_YES == must_kill)
281 {
240 if (0 == SafeTerminateProcess (proc->handle, 0, 0)) 282 if (0 == SafeTerminateProcess (proc->handle, 0, 0))
241 { 283 {
242 DWORD error_code = GetLastError (); 284 DWORD error_code = GetLastError ();
243 if ((error_code != WAIT_TIMEOUT) && (error_code != ERROR_PROCESS_ABORTED)) 285 if ( (error_code != WAIT_TIMEOUT) &&
286 (error_code != ERROR_PROCESS_ABORTED) )
244 { 287 {
245 LOG ((error_code == ERROR_ACCESS_DENIED) ? 288 LOG ((error_code == ERROR_ACCESS_DENIED) ?
246 GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING, 289 GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING,
247 "SafeTermiateProcess failed with code %lu\n", error_code); 290 "SafeTermiateProcess failed with code %lu\n",
291 error_code);
248 /* The problem here is that a process that is already dying 292 /* The problem here is that a process that is already dying
249 * might cause SafeTerminateProcess to fail with 293 * might cause SafeTerminateProcess to fail with
250 * ERROR_ACCESS_DENIED, but the process WILL die eventually. 294 * ERROR_ACCESS_DENIED, but the process WILL die eventually.
@@ -263,6 +307,7 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
263 } 307 }
264 } 308 }
265 } 309 }
310 }
266 } 311 }
267 return 0; 312 return 0;
268#else 313#else
@@ -277,12 +322,16 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
277 errno = EINVAL; 322 errno = EINVAL;
278 return -1; 323 return -1;
279#else 324#else
280 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via system call\n", sig, proc->pid); 325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Sending signal %d to pid: %u via system call\n",
327 sig,
328 proc->pid);
281 return PLIBC_KILL (proc->pid, sig); 329 return PLIBC_KILL (proc->pid, sig);
282#endif 330#endif
283 } 331 }
284} 332}
285 333
334
286/** 335/**
287 * Get the pid of the process in question 336 * Get the pid of the process in question
288 * 337 *
@@ -298,7 +347,8 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process * proc)
298 347
299 348
300/** 349/**
301 * Cleans up process structure contents (OS-dependent) and deallocates it 350 * Cleans up process structure contents (OS-dependent) and deallocates
351 * it.
302 * 352 *
303 * @param proc pointer to process structure 353 * @param proc pointer to process structure
304 */ 354 */
@@ -314,6 +364,7 @@ GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc)
314 GNUNET_free (proc); 364 GNUNET_free (proc);
315} 365}
316 366
367
317#if WINDOWS 368#if WINDOWS
318#include "gnunet_signal_lib.h" 369#include "gnunet_signal_lib.h"
319 370
@@ -324,6 +375,7 @@ extern GNUNET_SIGNAL_Handler w32_sigchld_handler;
324 */ 375 */
325#define DWORD_WINAPI DWORD WINAPI 376#define DWORD_WINAPI DWORD WINAPI
326 377
378
327/** 379/**
328 * @brief Waits for a process to terminate and invokes the SIGCHLD handler 380 * @brief Waits for a process to terminate and invokes the SIGCHLD handler
329 * @param proc pointer to process structure 381 * @param proc pointer to process structure
@@ -467,7 +519,9 @@ open_dev_null (int target_fd,
467 fd = open ("/dev/null", flags); 519 fd = open ("/dev/null", flags);
468 if (-1 == fd) 520 if (-1 == fd)
469 { 521 {
470 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", "/dev/null"); 522 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
523 "open",
524 "/dev/null");
471 return; 525 return;
472 } 526 }
473 if (fd == target_fd) 527 if (fd == target_fd)
@@ -531,23 +585,30 @@ start_process (int pipe_control,
531 int fd_stdin_read; 585 int fd_stdin_read;
532 int fd_stdin_write; 586 int fd_stdin_write;
533 587
534 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL)) 588 if (GNUNET_SYSERR ==
589 GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL))
535 return NULL; /* not executable */ 590 return NULL; /* not executable */
536 if (GNUNET_YES == pipe_control) 591 if (GNUNET_YES == pipe_control)
537 { 592 {
538 struct GNUNET_DISK_PipeHandle *childpipe; 593 struct GNUNET_DISK_PipeHandle *childpipe;
539 int dup_childpipe_read_fd = -1; 594 int dup_childpipe_read_fd = -1;
540 595
541 childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO); 596 childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
597 GNUNET_YES, GNUNET_NO);
542 if (NULL == childpipe) 598 if (NULL == childpipe)
543 return NULL; 599 return NULL;
544 childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ); 600 childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe,
545 childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE); 601 GNUNET_DISK_PIPE_END_READ);
602 childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe,
603 GNUNET_DISK_PIPE_END_WRITE);
546 GNUNET_DISK_pipe_close (childpipe); 604 GNUNET_DISK_pipe_close (childpipe);
547 if ((NULL == childpipe_read) || (NULL == childpipe_write) || 605 if ( (NULL == childpipe_read) ||
548 (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read, 606 (NULL == childpipe_write) ||
549 &childpipe_read_fd, sizeof (int))) || 607 (GNUNET_OK !=
550 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd)))) 608 GNUNET_DISK_internal_file_handle_ (childpipe_read,
609 &childpipe_read_fd,
610 sizeof (int))) ||
611 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))))
551 { 612 {
552 if (NULL != childpipe_read) 613 if (NULL != childpipe_read)
553 GNUNET_DISK_file_close (childpipe_read); 614 GNUNET_DISK_file_close (childpipe_read);
@@ -1762,17 +1823,19 @@ cmd_read (void *cls)
1762 1823
1763 cmd->rtask = NULL; 1824 cmd->rtask = NULL;
1764 tc = GNUNET_SCHEDULER_get_task_context (); 1825 tc = GNUNET_SCHEDULER_get_task_context ();
1765 if (GNUNET_YES != GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, cmd->r)) 1826 if (GNUNET_YES !=
1827 GNUNET_NETWORK_fdset_handle_isset (tc->read_ready,
1828 cmd->r))
1766 { 1829 {
1767 /* timeout, shutdown, etc. */ 1830 /* timeout */
1768 proc = cmd->proc; 1831 proc = cmd->proc;
1769 cmd->proc = NULL; 1832 cmd->proc = NULL;
1770 proc (cmd->proc_cls, NULL); 1833 proc (cmd->proc_cls, NULL);
1771 return; 1834 return;
1772 } 1835 }
1773 ret = 1836 ret = GNUNET_DISK_file_read (cmd->r,
1774 GNUNET_DISK_file_read (cmd->r, &cmd->buf[cmd->off], 1837 &cmd->buf[cmd->off],
1775 sizeof (cmd->buf) - cmd->off); 1838 sizeof (cmd->buf) - cmd->off);
1776 if (ret <= 0) 1839 if (ret <= 0)
1777 { 1840 {
1778 if ((cmd->off > 0) && (cmd->off < sizeof (cmd->buf))) 1841 if ((cmd->off > 0) && (cmd->off < sizeof (cmd->buf)))
@@ -1795,9 +1858,11 @@ cmd_read (void *cls)
1795 cmd->off -= (end + 1 - cmd->buf); 1858 cmd->off -= (end + 1 - cmd->buf);
1796 end = memchr (cmd->buf, '\n', cmd->off); 1859 end = memchr (cmd->buf, '\n', cmd->off);
1797 } 1860 }
1798 cmd->rtask = 1861 cmd->rtask
1799 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining 1862 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
1800 (cmd->timeout), cmd->r, &cmd_read, cmd); 1863 (cmd->timeout),
1864 cmd->r,
1865 &cmd_read, cmd);
1801} 1866}
1802 1867
1803 1868
@@ -1824,12 +1889,15 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc,
1824 struct GNUNET_DISK_PipeHandle *opipe; 1889 struct GNUNET_DISK_PipeHandle *opipe;
1825 va_list ap; 1890 va_list ap;
1826 1891
1827 opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); 1892 opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES,
1893 GNUNET_NO, GNUNET_YES);
1828 if (NULL == opipe) 1894 if (NULL == opipe)
1829 return NULL; 1895 return NULL;
1830 va_start (ap, binary); 1896 va_start (ap, binary);
1831 /* redirect stdout, don't inherit stderr/stdin */ 1897 /* redirect stdout, don't inherit stderr/stdin */
1832 eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, NULL, binary, ap); 1898 eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL,
1899 opipe, NULL, binary,
1900 ap);
1833 va_end (ap); 1901 va_end (ap);
1834 if (NULL == eip) 1902 if (NULL == eip)
1835 { 1903 {
@@ -1843,8 +1911,12 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc,
1843 cmd->opipe = opipe; 1911 cmd->opipe = opipe;
1844 cmd->proc = proc; 1912 cmd->proc = proc;
1845 cmd->proc_cls = proc_cls; 1913 cmd->proc_cls = proc_cls;
1846 cmd->r = GNUNET_DISK_pipe_handle (opipe, GNUNET_DISK_PIPE_END_READ); 1914 cmd->r = GNUNET_DISK_pipe_handle (opipe,
1847 cmd->rtask = GNUNET_SCHEDULER_add_read_file (timeout, cmd->r, &cmd_read, cmd); 1915 GNUNET_DISK_PIPE_END_READ);
1916 cmd->rtask = GNUNET_SCHEDULER_add_read_file (timeout,
1917 cmd->r,
1918 &cmd_read,
1919 cmd);
1848 return cmd; 1920 return cmd;
1849} 1921}
1850 1922