#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
VLOG_DEFINE_THIS_MODULE(process);
-COVERAGE_DEFINE(process_sigchld);
COVERAGE_DEFINE(process_start);
struct process {
void
process_init(void)
{
+#ifndef _WIN32
static bool inited;
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
xsigaction(SIGCHLD, &sa, NULL);
+#endif
}
char *
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.
int
process_start(char **argv, struct process **pp)
{
+#ifndef _WIN32
pid_t pid;
int error;
pid = fork();
if (pid < 0) {
- VLOG_WARN("fork failed: %s", strerror(errno));
+ VLOG_WARN("fork failed: %s", ovs_strerror(errno));
return errno;
} else if (pid) {
/* Running in parent process. */
}
execvp(argv[0], argv);
fprintf(stderr, "execvp(\"%s\") failed: %s\n",
- argv[0], strerror(errno));
+ argv[0], ovs_strerror(errno));
_exit(1);
}
+#else
+ *pp = NULL;
+ return ENOSYS;
+#endif
}
/* Destroys 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'. */
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)) {
if (WCOREDUMP(status)) {
ds_put_cstr(&ds, ", core dumped");
}
+#else
+ ds_put_cstr(&ds, "function not supported.");
+#endif
return ds_cstr(&ds);
}
void
process_run(void)
{
+#ifndef _WIN32
char buf[_POSIX_PIPE_BUF];
if (!list_is_empty(&all_processes) && read(fds[0], buf, sizeof buf) > 0) {
p->exited = true;
p->status = status;
} else if (retval < 0) {
- VLOG_WARN("waitpid: %s", strerror(errno));
+ VLOG_WARN("waitpid: %s", ovs_strerror(errno));
p->exited = true;
p->status = -1;
}
}
}
}
+#endif
}
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 *