2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/os_priority.c
23 * @brief Methods to set process priority
28 #include "gnunet_common.h"
29 #include "gnunet_os_lib.h"
32 * Set process priority
34 * @param proc id of the process
35 * @param prio priority value
36 * @return GNUNET_OK on success, GNUNET_SYSERR on error
39 GNUNET_OS_set_process_priority (pid_t proc,
40 enum GNUNET_SCHEDULER_Priority prio)
44 GNUNET_assert (prio < GNUNET_SCHEDULER_PRIORITY_COUNT);
45 if (prio == GNUNET_SCHEDULER_PRIORITY_KEEP)
47 /* convert to MINGW/Unix values */
50 case GNUNET_SCHEDULER_PRIORITY_DEFAULT:
52 rprio = NORMAL_PRIORITY_CLASS;
57 case GNUNET_SCHEDULER_PRIORITY_HIGH:
59 rprio = ABOVE_NORMAL_PRIORITY_CLASS;
64 case GNUNET_SCHEDULER_PRIORITY_BACKGROUND:
66 rprio = BELOW_NORMAL_PRIORITY_CLASS;
71 case GNUNET_SCHEDULER_PRIORITY_UI:
72 case GNUNET_SCHEDULER_PRIORITY_URGENT:
74 rprio = HIGH_PRIORITY_CLASS;
79 case GNUNET_SCHEDULER_PRIORITY_IDLE:
81 rprio = IDLE_PRIORITY_CLASS;
90 /* Set process priority */
92 SetPriorityClass (GetCurrentProcess (), rprio);
94 if (proc == getpid ())
97 if ((-1 == nice (rprio)) && (errno != 0))
99 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
100 GNUNET_ERROR_TYPE_BULK, "nice");
101 return GNUNET_SYSERR;
106 if (0 != setpriority (PRIO_PROCESS, proc, rprio))
109 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
110 GNUNET_ERROR_TYPE_BULK, "setpriority");
111 return GNUNET_SYSERR;
122 * @param filename name of the binary
123 * @param ... NULL-terminated list of arguments to the process
124 * @return process ID of the new process, -1 on error
127 GNUNET_OS_start_process (const char *filename, ...)
136 #if HAVE_WORKING_VFORK
145 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
149 #if HAVE_WORKING_VFORK
150 /* let's hope vfork actually works; for some extreme cases (including
151 a testcase) we need 'execvp' to have run before we return, since
152 we may send a signal to the process next and we don't want it
153 to be caught by OUR signal handler (but either by the default
154 handler or the actual handler as installed by the process itself). */
156 /* let's give the child process a chance to run execvp, 1s should
157 be plenty in practice */
164 va_start (ap, filename);
165 while (NULL != va_arg (ap, char *))
168 argv = GNUNET_malloc (sizeof (char *) * (argc + 1));
170 va_start (ap, filename);
171 while (NULL != (argv[argc] = va_arg (ap, char *)))
174 execvp (filename, argv);
175 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
182 PROCESS_INFORMATION proc;
187 va_start (ap, filename);
188 while (NULL != (arg = va_arg (ap, char *)))
189 cmdlen = cmdlen + strlen (arg) + 3;
192 cmd = idx = GNUNET_malloc (sizeof (char) * cmdlen);
193 va_start (ap, filename);
194 while (NULL != (arg = va_arg (ap, char *)))
195 idx += sprintf (idx, "\"%s\" ", arg);
198 memset (&start, 0, sizeof (start));
199 start.cb = sizeof (start);
201 len = strlen (filename);
202 if (strnicmp (filename + len - 4, ".exe", 4) == 0)
205 GNUNET_asprintf (&fn, "%s.exe", filename);
208 (fn, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start,
211 SetErrnoFromWinError (GetLastError ());
212 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", fn);
217 CloseHandle (proc.hProcess);
218 CloseHandle (proc.hThread);
222 return proc.dwProcessId;
232 * @param filename name of the binary
233 * @param argv NULL-terminated list of arguments to the process
234 * @return process ID of the new process, -1 on error
237 GNUNET_OS_start_process_v (const char *filename, char *const argv[])
242 #if HAVE_WORKING_VFORK
251 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
255 #if HAVE_WORKING_VFORK
256 /* let's hope vfork actually works; for some extreme cases (including
257 a testcase) we need 'execvp' to have run before we return, since
258 we may send a signal to the process next and we don't want it
259 to be caught by OUR signal handler (but either by the default
260 handler or the actual handler as installed by the process itself). */
262 /* let's give the child process a chance to run execvp, 1s should
263 be plenty in practice */
269 execvp (filename, argv);
270 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
277 PROCESS_INFORMATION proc;
283 cmdlen = cmdlen + strlen (*arg) + 3;
287 cmd = idx = GNUNET_malloc (sizeof (char) * cmdlen);
291 idx += sprintf (idx, "\"%s\" ", *arg);
295 memset (&start, 0, sizeof (start));
296 start.cb = sizeof (start);
299 (filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start,
302 SetErrnoFromWinError (GetLastError ());
303 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
306 CloseHandle (proc.hProcess);
307 CloseHandle (proc.hThread);
311 return proc.dwProcessId;
316 * Retrieve the status of a process
317 * @param proc process ID
318 * @param type status type
319 * @param code return code/signal number
320 * @return GNUNET_OK on success, GNUNET_NO if the process is still running, GNUNET_SYSERR otherwise
323 GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type,
330 GNUNET_assert (0 != proc);
331 ret = waitpid (proc, &status, WNOHANG);
334 *type = GNUNET_OS_PROCESS_RUNNING;
340 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
341 return GNUNET_SYSERR;
343 if (WIFEXITED (status))
345 *type = GNUNET_OS_PROCESS_EXITED;
346 *code = WEXITSTATUS (status);
348 else if (WIFSIGNALED (status))
350 *type = GNUNET_OS_PROCESS_SIGNALED;
351 *code = WTERMSIG (status);
353 else if (WIFSTOPPED (status))
355 *type = GNUNET_OS_PROCESS_SIGNALED;
356 *code = WSTOPSIG (status);
359 else if (WIFCONTINUED (status))
361 *type = GNUNET_OS_PROCESS_RUNNING;
367 *type = GNUNET_OS_PROCESS_UNKNOWN;
374 h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, proc);
375 if (INVALID_HANDLE_VALUE == h)
377 SetErrnoFromWinError (GetLastError ());
378 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "OpenProcess");
379 return GNUNET_SYSERR;
382 c = GetExitCodeProcess (proc, &c);
383 if (STILL_ACTIVE == c)
385 *type = GNUNET_OS_PROCESS_RUNNING;
390 *type = GNUNET_OS_PROCESS_EXITED;
400 * @param proc process ID to wait for
401 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
404 GNUNET_OS_process_wait (pid_t proc)
407 if (proc != waitpid (proc, NULL, 0))
408 return GNUNET_SYSERR;
416 h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, proc);
417 if (INVALID_HANDLE_VALUE == h)
419 SetErrnoFromWinError (GetLastError ());
420 return GNUNET_SYSERR;
423 if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE))
425 SetErrnoFromWinError (GetLastError ());
438 /* end of os_priority.c */