#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_start);
struct process {
- struct list node;
+ struct ovs_list node;
char *name;
pid_t pid;
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);
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.
#ifndef _WIN32
pid_t pid;
int error;
+ sigset_t prev_mask;
assert_single_threaded();
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();
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;