-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.
 
-     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
-     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>
 
-#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"
 
@@ -70,6 +68,11 @@ static struct GNUNET_OS_Process current_process;
  */
 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.
@@ -80,7 +83,7 @@ static void
 shutdown_pch (void *cls)
 {
   struct GNUNET_DISK_FileHandle *control_pipe = cls;
-    
+
   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;
+    GNUNET_SCHEDULER_cancel (spch);
+    spch = NULL;
     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;
 
+  (void) cls;
   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);
-  GNUNET_SCHEDULER_add_shutdown (&shutdown_pch,
-                                control_pipe);
+  spch = GNUNET_SCHEDULER_add_shutdown (&shutdown_pch,
+                                        control_pipe);
   putenv (GNUNET_OS_CONTROL_PIPE "=");
 }
 
@@ -1084,7 +1090,10 @@ start_process (int pipe_control,
                                        &lsocks_read, sizeof (HANDLE));
   }
   else
+  {
     lsocks_pipe = NULL;
+    lsocks_write_fd = NULL;
+  }
 
   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,
-                 "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;
     }
@@ -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,
-                   "Failed to duplicate an socket[%llu]: %u\n", i,
+                   "Failed to duplicate an socket[%u]: %lu\n", i,
                    GetLastError ());
         break;
       }
@@ -1250,7 +1259,7 @@ start_process (int pipe_control,
       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;
       }
@@ -1259,7 +1268,7 @@ start_process (int pipe_control,
       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;
       }
@@ -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
+ * @param options WNOHANG if non-blocking is desired
  * @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);
-  ret = waitpid (proc->pid, &status, WNOHANG);
+  ret = waitpid (proc->pid, &status, options);
   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
+#ifndef WNOHANG
+#define WNOHANG  42 /* just a flag for W32, purely internal at this point */
+#endif
+
   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 (WNOHANG != options)
+  {
+    if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE))
+    {
+      SetErrnoFromWinError (GetLastError ());
+      return GNUNET_SYSERR;
+    }
+  }
   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
@@ -1858,7 +1923,7 @@ cmd_read (void *cls)
     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,