-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[oweals/gnunet.git] / src / util / os_priority.c
index 2a6ea8321005ae00df08b3dd0a5a7a7cd13d79a1..a758f24f1da7678eb006f315a464e24e9458b550 100644 (file)
@@ -2,20 +2,18 @@
      This file is part of GNUnet
      Copyright (C) 2002, 2003, 2004, 2005, 2006, 2011 GNUnet e.V.
 
      This file is part of GNUnet
      Copyright (C) 2002, 2003, 2004, 2005, 2006, 2011 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /**
 */
 
 /**
 #include "disk.h"
 #include <unistr.h>
 
 #include "disk.h"
 #include <unistr.h>
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-os-priority", __VA_ARGS__)
 
 
-#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
+#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", syscall, filename)
+#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"
 
 
 #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE"
 
@@ -70,6 +68,11 @@ static struct GNUNET_OS_Process current_process;
  */
 static struct GNUNET_SCHEDULER_Task *pch;
 
  */
 static struct GNUNET_SCHEDULER_Task *pch;
 
+/**
+ * Handle for the #shutdown_pch() Task.
+ */
+static struct GNUNET_SCHEDULER_Task *spch;
+
 
 /**
  * This handler is called on shutdown to remove the #pch.
 
 /**
  * This handler is called on shutdown to remove the #pch.
@@ -80,7 +83,7 @@ static void
 shutdown_pch (void *cls)
 {
   struct GNUNET_DISK_FileHandle *control_pipe = cls;
 shutdown_pch (void *cls)
 {
   struct GNUNET_DISK_FileHandle *control_pipe = cls;
-    
+
   GNUNET_SCHEDULER_cancel (pch);
   pch = NULL;
   GNUNET_DISK_file_close (control_pipe);
   GNUNET_SCHEDULER_cancel (pch);
   pch = NULL;
   GNUNET_DISK_file_close (control_pipe);
@@ -114,6 +117,8 @@ parent_control_handler (void *cls)
         "Closing control pipe\n");
     GNUNET_DISK_file_close (control_pipe);
     control_pipe = NULL;
         "Closing control pipe\n");
     GNUNET_DISK_file_close (control_pipe);
     control_pipe = NULL;
+    GNUNET_SCHEDULER_cancel (spch);
+    spch = NULL;
     return;
   }
   pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE);
     return;
   }
   pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE);
@@ -147,6 +152,7 @@ GNUNET_OS_install_parent_control_handler (void *cls)
   struct GNUNET_DISK_FileHandle *control_pipe;
   uint64_t pipe_fd;
 
   struct GNUNET_DISK_FileHandle *control_pipe;
   uint64_t pipe_fd;
 
+  (void) cls;
   if (NULL != pch)
   {
     /* already done, we've been called twice... */
   if (NULL != pch)
   {
     /* already done, we've been called twice... */
@@ -205,8 +211,8 @@ GNUNET_OS_install_parent_control_handler (void *cls)
                                        control_pipe,
                                        &parent_control_handler,
                                        control_pipe);
                                        control_pipe,
                                        &parent_control_handler,
                                        control_pipe);
-  GNUNET_SCHEDULER_add_shutdown (&shutdown_pch,
-                                control_pipe);
+  spch = GNUNET_SCHEDULER_add_shutdown (&shutdown_pch,
+                                        control_pipe);
   putenv (GNUNET_OS_CONTROL_PIPE "=");
 }
 
   putenv (GNUNET_OS_CONTROL_PIPE "=");
 }
 
@@ -1084,7 +1090,10 @@ start_process (int pipe_control,
                                        &lsocks_read, sizeof (HANDLE));
   }
   else
                                        &lsocks_read, sizeof (HANDLE));
   }
   else
+  {
     lsocks_pipe = NULL;
     lsocks_pipe = NULL;
+    lsocks_write_fd = NULL;
+  }
 
   env_off = 0;
   if (GNUNET_YES == pipe_control)
 
   env_off = 0;
   if (GNUNET_YES == pipe_control)
@@ -1222,7 +1231,7 @@ start_process (int pipe_control,
     if (sizeof (count) != wrote)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     if (sizeof (count) != wrote)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Failed to write %u count bytes to the child: %u\n",
+                 "Failed to write %u count bytes to the child: %lu\n",
                  sizeof (count), GetLastError ());
       break;
     }
                  sizeof (count), GetLastError ());
       break;
     }
@@ -1233,7 +1242,7 @@ start_process (int pipe_control,
       if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid, &pi))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
       if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid, &pi))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                   "Failed to duplicate an socket[%llu]: %u\n", i,
+                   "Failed to duplicate an socket[%u]: %lu\n", i,
                    GetLastError ());
         break;
       }
                    GetLastError ());
         break;
       }
@@ -1250,7 +1259,7 @@ start_process (int pipe_control,
       if (sizeof (size) != wrote)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
       if (sizeof (size) != wrote)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                   "Failed to write %u size[%llu] bytes to the child: %u\n",
+                   "Failed to write %u size[%u] bytes to the child: %lu\n",
                    sizeof (size), i, GetLastError ());
         break;
       }
                    sizeof (size), i, GetLastError ());
         break;
       }
@@ -1259,7 +1268,7 @@ start_process (int pipe_control,
       if (sizeof (pi) != wrote)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
       if (sizeof (pi) != wrote)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                   "Failed to write %u socket[%llu] bytes to the child: %u\n",
+                   "Failed to write %u socket[%u] bytes to the child: %lu\n",
                    sizeof (pi), i, GetLastError ());
         break;
       }
                    sizeof (pi), i, GetLastError ());
         break;
       }
@@ -1579,25 +1588,27 @@ GNUNET_OS_start_process_s (int pipe_control,
 
 
 /**
 
 
 /**
- * Retrieve the status of a process, waiting on him if dead.
+ * Retrieve the status of a process, waiting on it if dead.
  * Nonblocking version.
  *
  * @param proc process ID
  * @param type status type
  * @param code return code/signal number
  * Nonblocking version.
  *
  * @param proc process ID
  * @param type status type
  * @param code return code/signal number
+ * @param options WNOHANG if non-blocking is desired
  * @return #GNUNET_OK on success, #GNUNET_NO if the process is still running, #GNUNET_SYSERR otherwise
  */
  * @return #GNUNET_OK on success, #GNUNET_NO if the process is still running, #GNUNET_SYSERR otherwise
  */
-int
-GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
-                          enum GNUNET_OS_ProcessStatusType *type,
-                          unsigned long *code)
+static int
+process_status (struct GNUNET_OS_Process *proc,
+                enum GNUNET_OS_ProcessStatusType *type,
+                unsigned long *code,
+                int options)
 {
 #ifndef MINGW
   int status;
   int ret;
 
   GNUNET_assert (0 != proc);
 {
 #ifndef MINGW
   int status;
   int ret;
 
   GNUNET_assert (0 != proc);
-  ret = waitpid (proc->pid, &status, WNOHANG);
+  ret = waitpid (proc->pid, &status, options);
   if (ret < 0)
   {
     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
   if (ret < 0)
   {
     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
@@ -1643,6 +1654,10 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
     *code = 0;
   }
 #else
     *code = 0;
   }
 #else
+#ifndef WNOHANG
+#define WNOHANG  42 /* just a flag for W32, purely internal at this point */
+#endif
+
   HANDLE h;
   DWORD c, error_code, ret;
 
   HANDLE h;
   DWORD c, error_code, ret;
 
@@ -1658,6 +1673,14 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
   if (h == NULL)
     h = GetCurrentProcess ();
 
   if (h == NULL)
     h = GetCurrentProcess ();
 
+  if (WNOHANG != options)
+  {
+    if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE))
+    {
+      SetErrnoFromWinError (GetLastError ());
+      return GNUNET_SYSERR;
+    }
+  }
   SetLastError (0);
   ret = GetExitCodeProcess (h, &c);
   error_code = GetLastError ();
   SetLastError (0);
   ret = GetExitCodeProcess (h, &c);
   error_code = GetLastError ();
@@ -1681,6 +1704,48 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
 }
 
 
 }
 
 
+/**
+ * Retrieve the status of a process, waiting on it if dead.
+ * Nonblocking version.
+ *
+ * @param proc process ID
+ * @param type status type
+ * @param code return code/signal number
+ * @return #GNUNET_OK on success, #GNUNET_NO if the process is still running, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
+                          enum GNUNET_OS_ProcessStatusType *type,
+                          unsigned long *code)
+{
+  return process_status (proc,
+                         type,
+                         code,
+                         WNOHANG);
+}
+
+
+/**
+ * Retrieve the status of a process, waiting on it if dead.
+ * Blocking version.
+ *
+ * @param proc pointer to process structure
+ * @param type status type
+ * @param code return code/signal number
+ * @return #GNUNET_OK on success, #GNUNET_NO if the process is still running, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_OS_process_wait_status (struct GNUNET_OS_Process *proc,
+                               enum GNUNET_OS_ProcessStatusType *type,
+                               unsigned long *code)
+{
+  return process_status (proc,
+                         type,
+                         code,
+                         0);
+}
+
+
 /**
  * Wait for a process to terminate. The return code is discarded.
  * You must not use #GNUNET_OS_process_status() on the same process
 /**
  * Wait for a process to terminate. The return code is discarded.
  * You must not use #GNUNET_OS_process_status() on the same process
@@ -1858,7 +1923,7 @@ cmd_read (void *cls)
     cmd->off -= (end + 1 - cmd->buf);
     end = memchr (cmd->buf, '\n', cmd->off);
   }
     cmd->off -= (end + 1 - cmd->buf);
     end = memchr (cmd->buf, '\n', cmd->off);
   }
-  cmd->rtask 
+  cmd->rtask
     = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
                                       (cmd->timeout),
                                      cmd->r,
     = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
                                       (cmd->timeout),
                                      cmd->r,