ovs-sandbox: Add note about OVN to initial output.
[cascardo/ovs.git] / lib / process.c
index 143347c..e89f9ca 100644 (file)
@@ -21,6 +21,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include "signals.h"
 #include "socket-util.h"
 #include "util.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(process);
 
-COVERAGE_DEFINE(process_sigchld);
 COVERAGE_DEFINE(process_start);
 
 struct process {
-    struct list node;
+    struct ovs_list node;
     char *name;
     pid_t pid;
 
@@ -54,7 +54,7 @@ struct process {
 static int fds[2];
 
 /* All processes. */
-static struct list all_processes = LIST_INITIALIZER(&all_processes);
+static struct ovs_list all_processes = OVS_LIST_INITIALIZER(&all_processes);
 
 static void sigchld_handler(int signr OVS_UNUSED);
 
@@ -69,6 +69,7 @@ static void sigchld_handler(int signr OVS_UNUSED);
 void
 process_init(void)
 {
+#ifndef _WIN32
     static bool inited;
     struct sigaction sa;
 
@@ -87,6 +88,7 @@ process_init(void)
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
     xsigaction(SIGCHLD, &sa, NULL);
+#endif
 }
 
 char *
@@ -164,6 +166,49 @@ process_register(const char *name, pid_t pid)
     return p;
 }
 
+#ifndef _WIN32
+static bool
+rlim_is_finite(rlim_t limit)
+{
+    if (limit == RLIM_INFINITY) {
+        return false;
+    }
+
+#ifdef RLIM_SAVED_CUR           /* FreeBSD 8.0 lacks RLIM_SAVED_CUR. */
+    if (limit == RLIM_SAVED_CUR) {
+        return false;
+    }
+#endif
+
+#ifdef RLIM_SAVED_MAX           /* FreeBSD 8.0 lacks RLIM_SAVED_MAX. */
+    if (limit == RLIM_SAVED_MAX) {
+        return false;
+    }
+#endif
+
+    return true;
+}
+
+/* Returns the maximum valid FD value, plus 1. */
+static int
+get_max_fds(void)
+{
+    static int max_fds;
+
+    if (!max_fds) {
+        struct rlimit r;
+        if (!getrlimit(RLIMIT_NOFILE, &r) && rlim_is_finite(r.rlim_cur)) {
+            max_fds = r.rlim_cur;
+        } else {
+            VLOG_WARN("failed to obtain fd limit, defaulting to 1024");
+            max_fds = 1024;
+        }
+    }
+
+    return max_fds;
+}
+#endif /* _WIN32 */
+
 /* Starts a subprocess with the arguments in the null-terminated argv[] array.
  * argv[0] is used as the name of the process.  Searches the PATH environment
  * variable to find the program to execute.
@@ -179,8 +224,10 @@ process_register(const char *name, pid_t pid)
 int
 process_start(char **argv, struct process **pp)
 {
+#ifndef _WIN32
     pid_t pid;
     int error;
+    sigset_t prev_mask;
 
     assert_single_threaded();
 
@@ -191,14 +238,15 @@ process_start(char **argv, struct process **pp)
         return error;
     }
 
+    fatal_signal_block(&prev_mask);
     pid = fork();
     if (pid < 0) {
         VLOG_WARN("fork failed: %s", ovs_strerror(errno));
-        return errno;
+        error = errno;
     } else if (pid) {
         /* Running in parent process. */
         *pp = process_register(argv[0], pid);
-        return 0;
+        error = 0;
     } else {
         /* Running in child process. */
         int fd_max = get_max_fds();
@@ -208,11 +256,18 @@ process_start(char **argv, struct process **pp)
         for (fd = 3; fd < fd_max; fd++) {
             close(fd);
         }
+        xpthread_sigmask(SIG_SETMASK, &prev_mask, NULL);
         execvp(argv[0], argv);
         fprintf(stderr, "execvp(\"%s\") failed: %s\n",
                 argv[0], ovs_strerror(errno));
         _exit(1);
     }
+    xpthread_sigmask(SIG_SETMASK, &prev_mask, NULL);
+    return error;
+#else
+    *pp = NULL;
+    return ENOSYS;
+#endif
 }
 
 /* Destroys process 'p'. */
@@ -231,9 +286,13 @@ process_destroy(struct process *p)
 int
 process_kill(const struct process *p, int signr)
 {
+#ifndef _WIN32
     return (p->exited ? ESRCH
             : !kill(p->pid, signr) ? 0
             : errno);
+#else
+    return ENOSYS;
+#endif
 }
 
 /* Returns the pid of process 'p'. */
@@ -276,6 +335,7 @@ char *
 process_status_msg(int status)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
+#ifndef _WIN32
     if (WIFEXITED(status)) {
         ds_put_format(&ds, "exit status %d", WEXITSTATUS(status));
     } else if (WIFSIGNALED(status)) {
@@ -294,6 +354,9 @@ process_status_msg(int status)
     if (WCOREDUMP(status)) {
         ds_put_cstr(&ds, ", core dumped");
     }
+#else
+    ds_put_cstr(&ds, "function not supported.");
+#endif
     return ds_cstr(&ds);
 }
 
@@ -301,6 +364,7 @@ process_status_msg(int status)
 void
 process_run(void)
 {
+#ifndef _WIN32
     char buf[_POSIX_PIPE_BUF];
 
     if (!list_is_empty(&all_processes) && read(fds[0], buf, sizeof buf) > 0) {
@@ -323,6 +387,7 @@ process_run(void)
             }
         }
     }
+#endif
 }
 
 
@@ -331,11 +396,15 @@ process_run(void)
 void
 process_wait(struct process *p)
 {
+#ifndef _WIN32
     if (p->exited) {
         poll_immediate_wake();
     } else {
         poll_fd_wait(fds[0], POLLIN);
     }
+#else
+    OVS_NOT_REACHED();
+#endif
 }
 
 char *