GNUnet  0.10.x
Data Structures | Macros | Functions | Variables
os_priority.c File Reference

Methods to set process priority. More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "disk.h"
#include <unistr.h>
Include dependency graph for os_priority.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_OS_Process
 
struct  GNUNET_OS_CommandHandle
 Handle to a command. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-os-priority", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)   GNUNET_log_from_strerror (kind, "util-os-priority", syscall)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)   GNUNET_log_from_strerror_file (kind, "util-os-priority", syscall, filename)
 
#define GNUNET_OS_CONTROL_PIPE   "GNUNET_OS_CONTROL_PIPE"
 

Functions

static void shutdown_pch (void *cls)
 This handler is called on shutdown to remove the pch. More...
 
static void parent_control_handler (void *cls)
 This handler is called when there are control data to be read on the pipe. More...
 
void GNUNET_OS_install_parent_control_handler (void *cls)
 Task that connects this process to its parent via pipe; essentially, the parent control handler will read signal numbers from the GNUNET_OS_CONTROL_PIPE (as given in an environment variable) and raise those signals. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_process_current ()
 Get process structure for current process. More...
 
int GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
 Sends a signal to the process. More...
 
pid_t GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc)
 Get the pid of the process in question. More...
 
void GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc)
 Cleans up process structure contents (OS-dependent) and deallocates it. More...
 
static void open_dev_null (int target_fd, int flags)
 Open '/dev/null' and make the result the given file descriptor. More...
 
static struct GNUNET_OS_Processstart_process (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const SOCKTYPE *lsocks, const char *filename, char *const argv[])
 Start a process. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_start_process_vap (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, char *const argv[])
 Start a process. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_start_process_va (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, va_list va)
 Start a process. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_start_process (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename,...)
 Start a process. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_start_process_v (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, const SOCKTYPE *lsocks, const char *filename, char *const argv[])
 Start a process. More...
 
struct GNUNET_OS_ProcessGNUNET_OS_start_process_s (int pipe_control, unsigned int std_inheritance, const SOCKTYPE *lsocks, const char *filename,...)
 Start a process. More...
 
static int process_status (struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code, int options)
 Retrieve the status of a process, waiting on it if dead. More...
 
int GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
 Retrieve the status of a process, waiting on it if dead. More...
 
int GNUNET_OS_process_wait_status (struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
 Retrieve the status of a process, waiting on it if dead. More...
 
int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc)
 Wait for a process to terminate. More...
 
void GNUNET_OS_command_stop (struct GNUNET_OS_CommandHandle *cmd)
 Stop/kill a command. More...
 
static void cmd_read (void *cls)
 Read from the process and call the line processor. More...
 
struct GNUNET_OS_CommandHandleGNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, struct GNUNET_TIME_Relative timeout, const char *binary,...)
 Run the given command line and call the given function for each line of the output. More...
 

Variables

static struct GNUNET_OS_Process current_process
 Handle for 'this' process. More...
 
static struct GNUNET_SCHEDULER_Taskpch
 Handle for the parent_control_handler() Task. More...
 
static struct GNUNET_SCHEDULER_Taskspch
 Handle for the shutdown_pch() Task. More...
 

Detailed Description

Methods to set process priority.

Author
Nils Durner

Definition in file os_priority.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-os-priority", __VA_ARGS__)

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)    GNUNET_log_from_strerror (kind, "util-os-priority", syscall)

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)    GNUNET_log_from_strerror_file (kind, "util-os-priority", syscall, filename)

Definition at line 36 of file os_priority.c.

Referenced by GNUNET_OS_install_parent_control_handler(), and start_process().

◆ GNUNET_OS_CONTROL_PIPE

#define GNUNET_OS_CONTROL_PIPE   "GNUNET_OS_CONTROL_PIPE"

Function Documentation

◆ shutdown_pch()

static void shutdown_pch ( void *  cls)
static

This handler is called on shutdown to remove the pch.

Parameters
clsthe struct GNUNET_DISK_FileHandle of the control pipe

Definition at line 85 of file os_priority.c.

References GNUNET_OS_Process::control_pipe, GNUNET_DISK_file_close(), and GNUNET_SCHEDULER_cancel().

Referenced by GNUNET_OS_install_parent_control_handler().

86 {
87  struct GNUNET_DISK_FileHandle *control_pipe = cls;
88 
90  pch = NULL;
91  GNUNET_DISK_file_close (control_pipe);
92  control_pipe = NULL;
93 }
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
static struct GNUNET_SCHEDULER_Task * pch
Handle for the parent_control_handler() Task.
Definition: os_priority.c:71
Handle used to access files (and pipes).
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parent_control_handler()

static void parent_control_handler ( void *  cls)
static

This handler is called when there are control data to be read on the pipe.

Parameters
clsthe struct GNUNET_DISK_FileHandle of the control pipe

Definition at line 102 of file os_priority.c.

References GNUNET_OS_Process::control_pipe, getenv(), GNUNET_assert, GNUNET_DISK_file_close(), GNUNET_DISK_file_read(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_OS_CONTROL_PIPE, GNUNET_SCHEDULER_add_read_file(), GNUNET_SCHEDULER_cancel(), GNUNET_SIGNAL_raise(), GNUNET_TIME_UNIT_FOREVER_REL, LOG, LOG_STRERROR, and ret.

Referenced by GNUNET_OS_install_parent_control_handler().

103 {
104  struct GNUNET_DISK_FileHandle *control_pipe = cls;
105  char sig;
106  char *pipe_fd;
107  ssize_t ret;
108 
109  pch = NULL;
110  ret = GNUNET_DISK_file_read (control_pipe,
111  &sig,
112  sizeof (sig));
113  if (sizeof (sig) != ret)
114  {
115  if (-1 == ret)
117  "GNUNET_DISK_file_read");
119  "Closing control pipe\n");
120  GNUNET_DISK_file_close (control_pipe);
121  control_pipe = NULL;
123  spch = NULL;
124  return;
125  }
126  pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE);
127  GNUNET_assert ( (NULL == pipe_fd) ||
128  (strlen (pipe_fd) <= 0) );
130  "Got control code %d from parent via pipe %s\n",
131  sig,
132  pipe_fd);
134  control_pipe,
136  control_pipe);
137  GNUNET_SIGNAL_raise ((int) sig);
138 }
void GNUNET_SIGNAL_raise(const int sig)
Raise the given signal by calling the installed signal handlers.
Definition: signal.c:120
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
#define GNUNET_OS_CONTROL_PIPE
Definition: os_priority.c:38
#define LOG_STRERROR(kind, syscall)
Definition: os_priority.c:34
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:881
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1643
static int ret
Final status code.
Definition: gnunet-arm.c:89
static struct GNUNET_SCHEDULER_Task * spch
Handle for the shutdown_pch() Task.
Definition: os_priority.c:76
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
char * getenv()
static struct GNUNET_SCHEDULER_Task * pch
Handle for the parent_control_handler() Task.
Definition: os_priority.c:71
static void parent_control_handler(void *cls)
This handler is called when there are control data to be read on the pipe.
Definition: os_priority.c:102
Handle used to access files (and pipes).
#define LOG(kind,...)
Definition: os_priority.c:32
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ open_dev_null()

static void open_dev_null ( int  target_fd,
int  flags 
)
static

Open '/dev/null' and make the result the given file descriptor.

Parameters
target_fddesired FD to point to /dev/null
flagsopen flags (O_RDONLY, O_WRONLY)

Definition at line 522 of file os_priority.c.

References GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_log_strerror, and GNUNET_log_strerror_file.

Referenced by start_process().

524 {
525  int fd;
526 
527  fd = open ("/dev/null", flags);
528  if (-1 == fd)
529  {
531  "open",
532  "/dev/null");
533  return;
534  }
535  if (fd == target_fd)
536  return;
537  if (-1 == dup2 (fd, target_fd))
538  {
540  (void) close (fd);
541  return;
542  }
543  GNUNET_break (0 == close (fd));
544 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
int fd
File handle on other OSes.
Here is the caller graph for this function:

◆ start_process()

static struct GNUNET_OS_Process* start_process ( int  pipe_control,
enum GNUNET_OS_InheritStdioFlags  std_inheritance,
struct GNUNET_DISK_PipeHandle pipe_stdin,
struct GNUNET_DISK_PipeHandle pipe_stdout,
struct GNUNET_DISK_PipeHandle pipe_stderr,
const SOCKTYPE lsocks,
const char *  filename,
char *const  argv[] 
)
static

Start a process.

Parameters
pipe_controlshould a pipe be used to send signals to the child?
std_inheritancea set of GNUNET_OS_INHERIT_STD_* flags controlling which std handles of the parent are inherited by the child. pipe_stdin and pipe_stdout take priority over std_inheritance (when they are non-NULL).
pipe_stdinpipe to use to send input to child process (or NULL)
pipe_stdoutpipe to use to get output from child process (or NULL)
pipe_stderrpipe to use for stderr for child process (or NULL)
lsocksarray of listen sockets to dup systemd-style (or NULL); must be NULL on platforms where dup is not supported
filenamename of the binary
argvNULL-terminated list of arguments to the process
Returns
process ID of the new process, -1 on error

Definition at line 566 of file os_priority.c.

References find_typedefs::arg, GNUNET_OS_Process::control_pipe, GNUNET_array_append, GNUNET_array_grow, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_DISK_file_close(), GNUNET_DISK_file_sync(), GNUNET_DISK_file_write(), GNUNET_DISK_internal_file_handle_(), GNUNET_DISK_pipe(), GNUNET_DISK_pipe_close(), GNUNET_DISK_pipe_close_end(), GNUNET_DISK_pipe_detach_end(), GNUNET_DISK_PIPE_END_READ, GNUNET_DISK_PIPE_END_WRITE, GNUNET_DISK_pipe_handle(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_free_non_null, GNUNET_log, GNUNET_malloc, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_OS_check_helper_binary(), GNUNET_OS_CONTROL_PIPE, GNUNET_OS_INHERIT_STD_ERR, GNUNET_OS_INHERIT_STD_IN, GNUNET_OS_INHERIT_STD_OUT, GNUNET_OS_installation_get_path(), GNUNET_OS_IPK_BINDIR, GNUNET_OS_IPK_LIBDIR, GNUNET_OS_IPK_SELF_PREFIX, GNUNET_snprintf(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_YES, INVALID_SOCKET, LOG, LOG_STRERROR, LOG_STRERROR_FILE, ls, open_dev_null(), pi, GNUNET_OS_Process::pid, plibc_conv_to_win_path(), ret, SafeTerminateProcess(), size, and start.

Referenced by GNUNET_OS_start_process_v(), and GNUNET_OS_start_process_vap().

574 {
575 #ifndef MINGW
576  pid_t ret;
577  char fds[16];
578  struct GNUNET_OS_Process *gnunet_proc;
579  struct GNUNET_DISK_FileHandle *childpipe_read;
580  struct GNUNET_DISK_FileHandle *childpipe_write;
581  int childpipe_read_fd;
582  int i;
583  int j;
584  int k;
585  int tgt;
586  int flags;
587  int *lscp;
588  unsigned int ls;
589  int fd_stdout_write;
590  int fd_stdout_read;
591  int fd_stderr_write;
592  int fd_stderr_read;
593  int fd_stdin_read;
594  int fd_stdin_write;
595 
596  if (GNUNET_SYSERR ==
598  return NULL; /* not executable */
599  if (GNUNET_YES == pipe_control)
600  {
601  struct GNUNET_DISK_PipeHandle *childpipe;
602  int dup_childpipe_read_fd = -1;
603 
604  childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
606  if (NULL == childpipe)
607  return NULL;
608  childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe,
610  childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe,
612  GNUNET_DISK_pipe_close (childpipe);
613  if ( (NULL == childpipe_read) ||
614  (NULL == childpipe_write) ||
615  (GNUNET_OK !=
616  GNUNET_DISK_internal_file_handle_ (childpipe_read,
617  &childpipe_read_fd,
618  sizeof (int))) ||
619  (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))))
620  {
621  if (NULL != childpipe_read)
622  GNUNET_DISK_file_close (childpipe_read);
623  if (NULL != childpipe_write)
624  GNUNET_DISK_file_close (childpipe_write);
625  if (0 <= dup_childpipe_read_fd)
626  close (dup_childpipe_read_fd);
627  return NULL;
628  }
629  childpipe_read_fd = dup_childpipe_read_fd;
630  GNUNET_DISK_file_close (childpipe_read);
631  }
632  else
633  {
634  childpipe_write = NULL;
635  childpipe_read_fd = -1;
636  }
637  if (NULL != pipe_stdin)
638  {
641  (pipe_stdin, GNUNET_DISK_PIPE_END_READ),
642  &fd_stdin_read, sizeof (int)));
645  (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE),
646  &fd_stdin_write, sizeof (int)));
647  }
648  if (NULL != pipe_stdout)
649  {
652  (pipe_stdout,
654  &fd_stdout_write, sizeof (int)));
657  (pipe_stdout, GNUNET_DISK_PIPE_END_READ),
658  &fd_stdout_read, sizeof (int)));
659  }
660  if (NULL != pipe_stderr)
661  {
664  (pipe_stderr,
666  &fd_stderr_read, sizeof (int)));
669  (pipe_stderr,
671  &fd_stderr_write, sizeof (int)));
672  }
673  lscp = NULL;
674  ls = 0;
675  if (NULL != lsocks)
676  {
677  i = 0;
678  while (-1 != (k = lsocks[i++]))
679  GNUNET_array_append (lscp, ls, k);
680  GNUNET_array_append (lscp, ls, -1);
681  }
682 #if DARWIN
683  /* see https://gnunet.org/vfork */
684  ret = vfork ();
685 #else
686  ret = fork ();
687 #endif
688  if (-1 == ret)
689  {
690  int eno = errno;
692  GNUNET_array_grow (lscp, ls, 0);
693  if (NULL != childpipe_write)
694  GNUNET_DISK_file_close (childpipe_write);
695  if (0 <= childpipe_read_fd)
696  close (childpipe_read_fd);
697  errno = eno;
698  return NULL;
699  }
700  if (0 != ret)
701  {
702  unsetenv (GNUNET_OS_CONTROL_PIPE);
703  gnunet_proc = GNUNET_new (struct GNUNET_OS_Process);
704  gnunet_proc->pid = ret;
705  gnunet_proc->control_pipe = childpipe_write;
706  if (GNUNET_YES == pipe_control)
707  {
708  close (childpipe_read_fd);
709  }
710  GNUNET_array_grow (lscp, ls, 0);
711  return gnunet_proc;
712  }
713  if (0 <= childpipe_read_fd)
714  {
715  char fdbuf[100];
716 #ifndef DARWIN
717  /* due to vfork, we must NOT free memory on DARWIN! */
718  GNUNET_DISK_file_close (childpipe_write);
719 #endif
720  snprintf (fdbuf, 100, "%x", childpipe_read_fd);
721  setenv (GNUNET_OS_CONTROL_PIPE, fdbuf, 1);
722  }
723  else
724  unsetenv (GNUNET_OS_CONTROL_PIPE);
725  if (NULL != pipe_stdin)
726  {
727  GNUNET_break (0 == close (fd_stdin_write));
728  if (-1 == dup2 (fd_stdin_read, 0))
730  GNUNET_break (0 == close (fd_stdin_read));
731  }
732  else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_IN))
733  {
734  GNUNET_break (0 == close (0));
735  open_dev_null (0, O_RDONLY);
736  }
737  if (NULL != pipe_stdout)
738  {
739  GNUNET_break (0 == close (fd_stdout_read));
740  if (-1 == dup2 (fd_stdout_write, 1))
742  GNUNET_break (0 == close (fd_stdout_write));
743  }
744  else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_OUT))
745  {
746  GNUNET_break (0 == close (1));
747  open_dev_null (1, O_WRONLY);
748  }
749  if (NULL != pipe_stderr)
750  {
751  GNUNET_break (0 == close (fd_stderr_read));
752  if (-1 == dup2 (fd_stderr_write, 2))
754  GNUNET_break (0 == close (fd_stderr_write));
755  }
756  else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
757  {
758  GNUNET_break (0 == close (2));
759  open_dev_null (2, O_WRONLY);
760  }
761  if (NULL != lscp)
762  {
763  /* read systemd documentation... */
764  i = 0;
765  tgt = 3;
766  while (-1 != lscp[i])
767  {
768  j = i + 1;
769  while (-1 != lscp[j])
770  {
771  if (lscp[j] == tgt)
772  {
773  /* dup away */
774  k = dup (lscp[j]);
775  GNUNET_assert (-1 != k);
776  GNUNET_assert (0 == close (lscp[j]));
777  lscp[j] = k;
778  break;
779  }
780  j++;
781  }
782  if (lscp[i] != tgt)
783  {
784  /* Bury any existing FD, no matter what; they should all be closed
785  * on exec anyway and the important onces have been dup'ed away */
786  (void) close (tgt);
787  GNUNET_assert (-1 != dup2 (lscp[i], tgt));
788  }
789  /* unset close-on-exec flag */
790  flags = fcntl (tgt, F_GETFD);
791  GNUNET_assert (flags >= 0);
792  flags &= ~FD_CLOEXEC;
793  fflush (stderr);
794  (void) fcntl (tgt, F_SETFD, flags);
795  tgt++;
796  i++;
797  }
798  GNUNET_snprintf (fds, sizeof (fds), "%u", i);
799  setenv ("LISTEN_FDS", fds, 1);
800  }
801 #ifndef DARWIN
802  /* due to vfork, we must NOT free memory on DARWIN! */
803  GNUNET_array_grow (lscp, ls, 0);
804 #endif
805  execvp (filename, argv);
807  _exit (1);
808 #else
809  struct GNUNET_DISK_FileHandle *childpipe_read;
810  struct GNUNET_DISK_FileHandle *childpipe_write;
811  HANDLE childpipe_read_handle;
812  char **arg;
813  char **non_const_argv;
814  unsigned int cmdlen;
815  char *cmd;
816  char *idx;
817  STARTUPINFOW start;
818  PROCESS_INFORMATION proc;
819  int argcount = 0;
820  struct GNUNET_OS_Process *gnunet_proc;
821  char path[MAX_PATH + 1];
822  char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
823  char *env_block = NULL;
824  char *pathbuf;
825  DWORD pathbuf_len;
826  DWORD alloc_len;
827  char *self_prefix;
828  char *bindir;
829  char *libdir;
830  char *ptr;
831  char *non_const_filename;
832  char win_path[MAX_PATH + 1];
833  struct GNUNET_DISK_PipeHandle *lsocks_pipe;
834  const struct GNUNET_DISK_FileHandle *lsocks_write_fd;
835  HANDLE lsocks_read;
836  HANDLE lsocks_write;
837  wchar_t *wpath;
838  wchar_t *wcmd;
839  size_t wpath_len;
840  size_t wcmd_len;
841  int env_off;
842  int fail;
843  long lRet;
844  HANDLE stdin_handle;
845  HANDLE stdout_handle;
846  HANDLE stdih, stdoh, stdeh;
847  DWORD stdif, stdof, stdef;
848  BOOL bresult;
849  DWORD error_code;
850  DWORD create_no_window;
851 
853  return NULL; /* not executable */
854 
855  /* Search in prefix dir (hopefully - the directory from which
856  * the current module was loaded), bindir and libdir, then in PATH
857  */
861 
862  pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0);
863 
864  alloc_len =
865  pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 +
866  strlen (libdir);
867 
868  pathbuf = GNUNET_malloc (alloc_len * sizeof (char));
869 
870  ptr = pathbuf;
871  ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
872  GNUNET_free (self_prefix);
873  GNUNET_free (bindir);
874  GNUNET_free (libdir);
875 
876  alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len);
877  if (alloc_len != pathbuf_len - 1)
878  {
879  GNUNET_free (pathbuf);
880  errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */
881  return NULL;
882  }
883 
884  cmdlen = strlen (filename);
885  if ( (cmdlen < 5) || (0 != strcmp (&filename[cmdlen - 4], ".exe")) )
886  GNUNET_asprintf (&non_const_filename, "%s.exe", filename);
887  else
888  GNUNET_asprintf (&non_const_filename, "%s", filename);
889 
890  /* It could be in POSIX form, convert it to a DOS path early on */
891  if (ERROR_SUCCESS != (lRet = plibc_conv_to_win_path (non_const_filename, win_path)))
892  {
893  SetErrnoFromWinError (lRet);
894  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "plibc_conv_to_win_path",
895  non_const_filename);
896  GNUNET_free (non_const_filename);
897  GNUNET_free (pathbuf);
898  return NULL;
899  }
900  GNUNET_free (non_const_filename);
901  non_const_filename = GNUNET_strdup (win_path);
902  /* Check that this is the full path. If it isn't, search. */
903  /* FIXME: convert it to wchar_t and use SearchPathW?
904  * Remember: arguments to _start_process() are technically in UTF-8...
905  */
906  if (non_const_filename[1] == ':')
907  {
908  snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename);
910  "Using path `%s' as-is. PATH is %s\n", path, ptr);
911  }
912  else if (!SearchPathA
913  (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char),
914  path, NULL))
915  {
916  SetErrnoFromWinError (GetLastError ());
918  non_const_filename);
919  GNUNET_free (non_const_filename);
920  GNUNET_free (pathbuf);
921  return NULL;
922  }
923  else
925  "Found `%s' in PATH `%s'\n", path, pathbuf);
926  GNUNET_free (pathbuf);
927  GNUNET_free (non_const_filename);
928 
929  /* Count the number of arguments */
930  arg = (char **) argv;
931  while (*arg)
932  {
933  arg++;
934  argcount++;
935  }
936 
937  /* Allocate a copy argv */
938  non_const_argv = GNUNET_malloc (sizeof (char *) * (argcount + 1));
939 
940  /* Copy all argv strings */
941  argcount = 0;
942  arg = (char **) argv;
943  while (*arg)
944  {
945  if (arg == argv)
946  non_const_argv[argcount] = GNUNET_strdup (path);
947  else
948  non_const_argv[argcount] = GNUNET_strdup (*arg);
949  arg++;
950  argcount++;
951  }
952  non_const_argv[argcount] = NULL;
953 
954  /* Count cmd len */
955  cmdlen = 1;
956  arg = non_const_argv;
957  while (*arg)
958  {
959  cmdlen = cmdlen + strlen (*arg) + 4;
960  arg++;
961  }
962 
963  /* Allocate and create cmd */
964  cmd = idx = GNUNET_malloc (sizeof (char) * cmdlen);
965  arg = non_const_argv;
966  while (*arg)
967  {
968  char arg_last_char = (*arg)[strlen (*arg) - 1];
969  idx += sprintf (idx, "\"%s%s\"%s", *arg,
970  arg_last_char == '\\' ? "\\" : "", *(arg + 1) ? " " : "");
971  arg++;
972  }
973 
974  while (argcount > 0)
975  GNUNET_free (non_const_argv[--argcount]);
976  GNUNET_free (non_const_argv);
977 
978  memset (&start, 0, sizeof (start));
979  start.cb = sizeof (start);
980  if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0))
981  start.dwFlags |= STARTF_USESTDHANDLES;
982 
983  stdih = GetStdHandle (STD_INPUT_HANDLE);
984  GetHandleInformation (stdih, &stdif);
985  if (pipe_stdin != NULL)
986  {
988  (pipe_stdin, GNUNET_DISK_PIPE_END_READ),
989  &stdin_handle, sizeof (HANDLE));
990  start.hStdInput = stdin_handle;
991  }
992  else if (stdih)
993  {
994  if (std_inheritance & GNUNET_OS_INHERIT_STD_IN)
995  {
996  SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 1);
997  if (pipe_stdin == NULL)
998  start.hStdInput = stdih;
999  }
1000  else
1001  SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 0);
1002  }
1003 
1004 
1005  stdoh = GetStdHandle (STD_OUTPUT_HANDLE);
1006  GetHandleInformation (stdoh, &stdof);
1007  if (NULL != pipe_stdout)
1008  {
1010  (pipe_stdout,
1012  &stdout_handle, sizeof (HANDLE));
1013  start.hStdOutput = stdout_handle;
1014  }
1015  else if (stdoh)
1016  {
1017  if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT)
1018  {
1019  SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 1);
1020  if (pipe_stdout == NULL)
1021  start.hStdOutput = stdoh;
1022  }
1023  else
1024  SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 0);
1025  }
1026 
1027  stdeh = GetStdHandle (STD_ERROR_HANDLE);
1028  GetHandleInformation (stdeh, &stdef);
1029  if (stdeh)
1030  {
1031  if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR)
1032  {
1033  SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 1);
1034  start.hStdError = stdeh;
1035  }
1036  else
1037  SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 0);
1038  }
1039 
1040  if (GNUNET_YES == pipe_control)
1041  {
1042  struct GNUNET_DISK_PipeHandle *childpipe;
1044  if (NULL == childpipe)
1045  return NULL;
1046  childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ);
1047  childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE);
1048  GNUNET_DISK_pipe_close (childpipe);
1049  if ((NULL == childpipe_read) || (NULL == childpipe_write) ||
1050  (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read,
1051  &childpipe_read_handle, sizeof (HANDLE))))
1052  {
1053  if (childpipe_read)
1054  GNUNET_DISK_file_close (childpipe_read);
1055  if (childpipe_write)
1056  GNUNET_DISK_file_close (childpipe_write);
1057  GNUNET_free (cmd);
1058  return NULL;
1059  }
1060  /* Unlike *nix variant, we don't dup the handle, so can't close
1061  * filehandle right now.
1062  */
1063  SetHandleInformation (childpipe_read_handle, HANDLE_FLAG_INHERIT, 1);
1064  }
1065  else
1066  {
1067  childpipe_read = NULL;
1068  childpipe_write = NULL;
1069  }
1070 
1071  if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
1072  {
1074 
1075  if (lsocks_pipe == NULL)
1076  {
1077  GNUNET_free (cmd);
1078  GNUNET_DISK_pipe_close (lsocks_pipe);
1079  if (GNUNET_YES == pipe_control)
1080  {
1081  GNUNET_DISK_file_close (childpipe_write);
1082  GNUNET_DISK_file_close (childpipe_read);
1083  }
1084  return NULL;
1085  }
1086  lsocks_write_fd = GNUNET_DISK_pipe_handle (lsocks_pipe,
1088  GNUNET_DISK_internal_file_handle_ (lsocks_write_fd,
1089  &lsocks_write, sizeof (HANDLE));
1091  (lsocks_pipe, GNUNET_DISK_PIPE_END_READ),
1092  &lsocks_read, sizeof (HANDLE));
1093  }
1094  else
1095  {
1096  lsocks_pipe = NULL;
1097  lsocks_write_fd = NULL;
1098  }
1099 
1100  env_off = 0;
1101  if (GNUNET_YES == pipe_control)
1102  {
1103  GNUNET_asprintf (&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE);
1104  GNUNET_asprintf (&our_env[env_off++], "%p", childpipe_read_handle);
1105  }
1106  if ( (lsocks != NULL) && (lsocks[0] != INVALID_SOCKET))
1107  {
1108  /*This will tell the child that we're going to send lsocks over the pipe*/
1109  GNUNET_asprintf (&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS");
1110  GNUNET_asprintf (&our_env[env_off++], "%lu", lsocks_read);
1111  }
1112  our_env[env_off++] = NULL;
1113  env_block = CreateCustomEnvTable (our_env);
1114  while (0 > env_off)
1115  GNUNET_free_non_null (our_env[--env_off]);
1116 
1117  wpath_len = 0;
1118  if (NULL == (wpath = u8_to_u16 ((uint8_t *) path, 1 + strlen (path), NULL, &wpath_len)))
1119  {
1121  "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno);
1122  GNUNET_free (env_block);
1123  GNUNET_free (cmd);
1124  if (lsocks_pipe)
1125  GNUNET_DISK_pipe_close (lsocks_pipe);
1126  if (GNUNET_YES == pipe_control)
1127  {
1128  GNUNET_DISK_file_close (childpipe_write);
1129  GNUNET_DISK_file_close (childpipe_read);
1130  }
1131  return NULL;
1132  }
1133 
1134  wcmd_len = 0;
1135  if (NULL == (wcmd = u8_to_u16 ((uint8_t *) cmd, 1 + strlen (cmd), NULL, &wcmd_len)))
1136  {
1138  "Failed to convert `%s' from UTF-8 to UTF-16: %d\n",
1139  cmd,
1140  errno);
1141  GNUNET_free (env_block);
1142  GNUNET_free (cmd);
1143  free (wpath);
1144  if (lsocks_pipe)
1145  GNUNET_DISK_pipe_close (lsocks_pipe);
1146  if (GNUNET_YES == pipe_control)
1147  {
1148  GNUNET_DISK_file_close (childpipe_write);
1149  GNUNET_DISK_file_close (childpipe_read);
1150  }
1151  return NULL;
1152  }
1153 
1154  create_no_window = 0;
1155  {
1156  HANDLE console_input = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1157  if (INVALID_HANDLE_VALUE == console_input)
1158  create_no_window = CREATE_NO_WINDOW;
1159  else
1160  CloseHandle (console_input);
1161  }
1162 
1163  bresult = CreateProcessW (wpath, wcmd, NULL, NULL, GNUNET_YES,
1164  create_no_window | CREATE_SUSPENDED, env_block, NULL, &start, &proc);
1165  error_code = GetLastError ();
1166 
1167  if ((NULL == pipe_stdin) && (stdih))
1168  SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, stdif);
1169 
1170 
1171  if ((NULL == pipe_stdout) && (stdoh))
1172  SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, stdof);
1173 
1174  if (stdeh)
1175  SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, stdef);
1176 
1177  if (!bresult)
1179  "CreateProcess(%s, %s) failed: %lu\n",
1180  path,
1181  cmd,
1182  error_code);
1183 
1184  GNUNET_free (env_block);
1185  GNUNET_free (cmd);
1186  free (wpath);
1187  free (wcmd);
1188  if (GNUNET_YES == pipe_control)
1189  {
1190  GNUNET_DISK_file_close (childpipe_read);
1191  }
1192 
1193  if (!bresult)
1194  {
1195  if (GNUNET_YES == pipe_control)
1196  {
1197  GNUNET_DISK_file_close (childpipe_write);
1198  }
1199  if (NULL != lsocks)
1200  GNUNET_DISK_pipe_close (lsocks_pipe);
1201  SetErrnoFromWinError (error_code);
1202  return NULL;
1203  }
1204 
1205  gnunet_proc = GNUNET_new (struct GNUNET_OS_Process);
1206  gnunet_proc->pid = proc.dwProcessId;
1207  gnunet_proc->handle = proc.hProcess;
1208  gnunet_proc->control_pipe = childpipe_write;
1209 
1210  CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL);
1211 
1212  ResumeThread (proc.hThread);
1213  CloseHandle (proc.hThread);
1214 
1215  if ( (NULL == lsocks) || (INVALID_SOCKET == lsocks[0]) )
1216  return gnunet_proc;
1217 
1219 
1220  /* This is a replacement for "goto error" that doesn't use goto */
1221  fail = 1;
1222  do
1223  {
1224  ssize_t wrote;
1225  uint64_t size;
1226  uint64_t count;
1227  unsigned int i;
1228 
1229  /* Tell the number of sockets */
1230  for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++);
1231 
1232  wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count));
1233  if (sizeof (count) != wrote)
1234  {
1236  "Failed to write %u count bytes to the child: %lu\n",
1237  sizeof (count), GetLastError ());
1238  break;
1239  }
1240  for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++)
1241  {
1242  WSAPROTOCOL_INFOA pi;
1243  /* Get a socket duplication info */
1244  if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid, &pi))
1245  {
1247  "Failed to duplicate an socket[%u]: %lu\n", i,
1248  GetLastError ());
1249  break;
1250  }
1251  /* Synchronous I/O is not nice, but we can't schedule this:
1252  * lsocks will be closed/freed by the caller soon, and until
1253  * the child creates a duplicate, closing a socket here will
1254  * close it for good.
1255  */
1256  /* Send the size of the structure
1257  * (the child might be built with different headers...)
1258  */
1259  size = sizeof (pi);
1260  wrote = GNUNET_DISK_file_write (lsocks_write_fd, &size, sizeof (size));
1261  if (sizeof (size) != wrote)
1262  {
1264  "Failed to write %u size[%u] bytes to the child: %lu\n",
1265  sizeof (size), i, GetLastError ());
1266  break;
1267  }
1268  /* Finally! Send the data */
1269  wrote = GNUNET_DISK_file_write (lsocks_write_fd, &pi, sizeof (pi));
1270  if (sizeof (pi) != wrote)
1271  {
1273  "Failed to write %u socket[%u] bytes to the child: %lu\n",
1274  sizeof (pi), i, GetLastError ());
1275  break;
1276  }
1277  }
1278  /* This will block us until the child makes a final read or closes
1279  * the pipe (hence no 'wrote' check), since we have to wait for it
1280  * to duplicate the last socket, before we return and start closing
1281  * our own copies)
1282  */
1283  wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count));
1284  fail = 0;
1285  }
1286  while (fail);
1287 
1288  GNUNET_DISK_file_sync (lsocks_write_fd);
1289  GNUNET_DISK_pipe_close (lsocks_pipe);
1290 
1291  if (fail)
1292  {
1293  /* If we can't pass on the socket(s), the child will block forever,
1294  * better put it out of its misery.
1295  */
1296  SafeTerminateProcess (gnunet_proc->handle, 0, 0);
1297  CloseHandle (gnunet_proc->handle);
1298  if (NULL != gnunet_proc->control_pipe)
1299  GNUNET_DISK_file_close (gnunet_proc->control_pipe);
1300  GNUNET_free (gnunet_proc);
1301  return NULL;
1302  }
1303  return gnunet_proc;
1304 #endif
1305 }
int GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:2133
When this flag is set, the child process will inherit stderr of the parent.
Definition: gnunet_os_lib.h:92
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1817
#define GNUNET_OS_CONTROL_PIPE
Definition: os_priority.c:38
#define LOG_STRERROR(kind, syscall)
Definition: os_priority.c:34
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
Terminate a process by creating a remote thread within it, which proceeds to call ExitProcess() insid...
Definition: win.c:1288
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
Return the directory where libraries are installed.
pid_t pid
PID of the process.
Definition: os_priority.c:46
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
When this flag is set, the child process will inherit stdin of the parent.
Definition: gnunet_os_lib.h:80
static void open_dev_null(int target_fd, int flags)
Open &#39;/dev/null&#39; and make the result the given file descriptor.
Definition: os_priority.c:522
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:2641
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define INVALID_SOCKET
Definition: network.c:39
struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Detaches one of the ends from the pipe.
Definition: disk.c:2570
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:1049
When this flag is set, the child process will inherit stdout of the parent.
Definition: gnunet_os_lib.h:86
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory.
static char * filename
The writing-end of a pipe.
The reading-end of a pipe.
int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows)
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(int blocking_read, int blocking_write, int inherit_read, int inherit_write)
Creates an interprocess channel.
Definition: disk.c:2289
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len)
Retrieve OS file handle.
Definition: disk.c:2665
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: os_priority.c:36
Return the installation directory of this application, not the one of the overall GNUnet installation...
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:2603
Return the directory where the program binaries are installed.
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
int GNUNET_DISK_pipe_close_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Closes one half of an interprocess channel.
Definition: disk.c:2532
struct GNUNET_DISK_FileHandle * control_pipe
Pipe we use to signal the process.
Definition: os_priority.c:59
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:80
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:66
#define LOG(kind,...)
Definition: os_priority.c:32
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_status()

static int process_status ( struct GNUNET_OS_Process proc,
enum GNUNET_OS_ProcessStatusType type,
unsigned long *  code,
int  options 
)
static

Retrieve the status of a process, waiting on it if dead.

Nonblocking version.

Parameters
procprocess ID
typestatus type
codereturn code/signal number
optionsWNOHANG if non-blocking is desired
Returns
GNUNET_OK on success, GNUNET_NO if the process is still running, GNUNET_SYSERR otherwise

Definition at line 1603 of file os_priority.c.

References GNUNET_assert, GNUNET_ERROR_TYPE_WARNING, GNUNET_NO, GNUNET_OK, GNUNET_OS_PROCESS_EXITED, GNUNET_OS_PROCESS_RUNNING, GNUNET_OS_PROCESS_SIGNALED, GNUNET_OS_PROCESS_UNKNOWN, GNUNET_SYSERR, h, LOG, LOG_STRERROR, GNUNET_OS_Process::pid, ret, and status.

Referenced by GNUNET_OS_process_status(), and GNUNET_OS_process_wait_status().

1607 {
1608 #ifndef MINGW
1609  int status;
1610  int ret;
1611 
1612  GNUNET_assert (0 != proc);
1613  ret = waitpid (proc->pid, &status, options);
1614  if (ret < 0)
1615  {
1617  "waitpid");
1618  return GNUNET_SYSERR;
1619  }
1620  if (0 == ret)
1621  {
1623  *code = 0;
1624  return GNUNET_NO;
1625  }
1626  if (proc->pid != ret)
1627  {
1629  return GNUNET_SYSERR;
1630  }
1631  if (WIFEXITED (status))
1632  {
1634  *code = WEXITSTATUS (status);
1635  }
1636  else if (WIFSIGNALED (status))
1637  {
1639  *code = WTERMSIG (status);
1640  }
1641  else if (WIFSTOPPED (status))
1642  {
1644  *code = WSTOPSIG (status);
1645  }
1646 #ifdef WIFCONTINUED
1647  else if (WIFCONTINUED (status))
1648  {
1650  *code = 0;
1651  }
1652 #endif
1653  else
1654  {
1656  *code = 0;
1657  }
1658 #else
1659 #ifndef WNOHANG
1660 #define WNOHANG 42 /* just a flag for W32, purely internal at this point */
1661 #endif
1662 
1663  HANDLE h;
1664  DWORD c, error_code, ret;
1665 
1666  h = proc->handle;
1667  ret = proc->pid;
1668  if (h == NULL || ret == 0)
1669  {
1671  "Invalid process information {%d, %08X}\n",
1672  ret, h);
1673  return GNUNET_SYSERR;
1674  }
1675  if (h == NULL)
1676  h = GetCurrentProcess ();
1677 
1678  if (WNOHANG != options)
1679  {
1680  if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE))
1681  {
1682  SetErrnoFromWinError (GetLastError ());
1683  return GNUNET_SYSERR;
1684  }
1685  }
1686  SetLastError (0);
1687  ret = GetExitCodeProcess (h, &c);
1688  error_code = GetLastError ();
1689  if (ret == 0 || error_code != NO_ERROR)
1690  {
1691  SetErrnoFromWinError (error_code);
1692  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetExitCodeProcess");
1693  return GNUNET_SYSERR;
1694  }
1695  if (STILL_ACTIVE == c)
1696  {
1698  *code = 0;
1699  return GNUNET_NO;
1700  }
1702  *code = c;
1703 #endif
1704 
1705  return GNUNET_OK;
1706 }
#define LOG_STRERROR(kind, syscall)
Definition: os_priority.c:34
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
pid_t pid
PID of the process.
Definition: os_priority.c:46
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static int ret
Final status code.
Definition: gnunet-arm.c:89
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
uint16_t status
See PRISM_STATUS_*-constants.
The process exited with a return code.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
The process was killed by a signal.
The process is still running.
The process is not known to the OS (or at least not one of our children).
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define LOG(kind,...)
Definition: os_priority.c:32
Here is the caller graph for this function:

◆ cmd_read()

static void cmd_read ( void *  cls)
static

Read from the process and call the line processor.

Parameters
clsthe struct GNUNET_OS_CommandHandle *

Definition at line 1883 of file os_priority.c.

References GNUNET_OS_CommandHandle::buf, end, GNUNET_DISK_file_read(), GNUNET_NETWORK_fdset_handle_isset(), GNUNET_SCHEDULER_add_read_file(), GNUNET_SCHEDULER_get_task_context(), GNUNET_TIME_absolute_get_remaining(), GNUNET_YES, GNUNET_OS_CommandHandle::off, GNUNET_OS_CommandHandle::proc, GNUNET_OS_CommandHandle::proc_cls, GNUNET_OS_CommandHandle::r, GNUNET_SCHEDULER_TaskContext::read_ready, ret, GNUNET_OS_CommandHandle::rtask, tc, and GNUNET_OS_CommandHandle::timeout.

Referenced by GNUNET_OS_command_run().

1884 {
1885  struct GNUNET_OS_CommandHandle *cmd = cls;
1886  const struct GNUNET_SCHEDULER_TaskContext *tc;
1888  char *end;
1889  ssize_t ret;
1890 
1891  cmd->rtask = NULL;
1893  if (GNUNET_YES !=
1895  cmd->r))
1896  {
1897  /* timeout */
1898  proc = cmd->proc;
1899  cmd->proc = NULL;
1900  proc (cmd->proc_cls, NULL);
1901  return;
1902  }
1903  ret = GNUNET_DISK_file_read (cmd->r,
1904  &cmd->buf[cmd->off],
1905  sizeof (cmd->buf) - cmd->off);
1906  if (ret <= 0)
1907  {
1908  if ((cmd->off > 0) && (cmd->off < sizeof (cmd->buf)))
1909  {
1910  cmd->buf[cmd->off] = '\0';
1911  cmd->proc (cmd->proc_cls, cmd->buf);
1912  }
1913  proc = cmd->proc;
1914  cmd->proc = NULL;
1915  proc (cmd->proc_cls, NULL);
1916  return;
1917  }
1918  end = memchr (&cmd->buf[cmd->off], '\n', ret);
1919  cmd->off += ret;
1920  while (NULL != end)
1921  {
1922  *end = '\0';
1923  cmd->proc (cmd->proc_cls, cmd->buf);
1924  memmove (cmd->buf, end + 1, cmd->off - (end + 1 - cmd->buf));
1925  cmd->off -= (end + 1 - cmd->buf);
1926  end = memchr (cmd->buf, '\n', cmd->off);
1927  }
1928  cmd->rtask
1930  (cmd->timeout),
1931  cmd->r,
1932  &cmd_read, cmd);
1933 }
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:746
char buf[1024]
Buffer for the output.
Definition: os_priority.c:1835
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:881
Context information passed to each scheduler task.
const struct GNUNET_DISK_FileHandle * r
Read-end of output pipe.
Definition: os_priority.c:1820
size_t off
Current read offset in buf.
Definition: os_priority.c:1850
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:417
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1643
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
static int ret
Final status code.
Definition: gnunet-arm.c:89
struct GNUNET_TIME_Absolute timeout
When to time out.
Definition: os_priority.c:1845
void * proc_cls
Closure for proc.
Definition: os_priority.c:1830
static void cmd_read(void *cls)
Read from the process and call the line processor.
Definition: os_priority.c:1883
struct GNUNET_SCHEDULER_Task * rtask
Task reading from pipe.
Definition: os_priority.c:1840
int GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h)
Check if a file handle is part of an fd set.
Definition: network.c:1419
Handle to a command.
Definition: os_priority.c:1804
GNUNET_OS_LineProcessor proc
Function to call on each line of output.
Definition: os_priority.c:1825
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
#define GNUNET_YES
Definition: gnunet_common.h:80
void(* GNUNET_OS_LineProcessor)(void *cls, const char *line)
Type of a function to process a line of output.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ current_process

struct GNUNET_OS_Process current_process
static

Handle for 'this' process.

Definition at line 66 of file os_priority.c.

Referenced by GNUNET_OS_process_current().

◆ pch

struct GNUNET_SCHEDULER_Task* pch
static

Handle for the parent_control_handler() Task.

Definition at line 71 of file os_priority.c.

Referenced by extract_filename(), and UnpackHostEnt().

◆ spch

struct GNUNET_SCHEDULER_Task* spch
static

Handle for the shutdown_pch() Task.

Definition at line 76 of file os_priority.c.