summaryrefslogtreecommitdiff
path: root/Utilities/cmlibuv/src/unix/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/process.c')
-rw-r--r--Utilities/cmlibuv/src/unix/process.c159
1 files changed, 127 insertions, 32 deletions
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index f2fe30521..f4826bf62 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
+#include <sched.h>
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
@@ -44,6 +45,16 @@ extern char **environ;
# include <grp.h>
#endif
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__)
+# define uv__cpu_set_t cpu_set_t
+#elif defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# include <pthread_np.h>
+# define uv__cpu_set_t cpuset_t
+#endif
+#endif
static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
@@ -126,7 +137,7 @@ int uv__make_socketpair(int fds[2], int flags) {
* Anything else is a genuine error.
*/
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
no_cloexec = 1;
@@ -134,7 +145,7 @@ skip:
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -159,7 +170,7 @@ int uv__make_pipe(int fds[2], int flags) {
return 0;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_pipe2 = 1;
@@ -167,7 +178,7 @@ skip:
#endif
if (pipe(fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -198,7 +209,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
case UV_CREATE_PIPE:
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
- return -EINVAL;
+ return UV_EINVAL;
else
return uv__make_socketpair(fds, 0);
@@ -210,21 +221,20 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
fd = uv__stream_fd(container->data.stream);
if (fd == -1)
- return -EINVAL;
+ return UV_EINVAL;
fds[1] = fd;
return 0;
default:
assert(0 && "Unexpected flags");
- return -EINVAL;
+ return UV_EINVAL;
}
}
static int uv__process_open_stream(uv_stdio_container_t* container,
- int pipefds[2],
- int writable) {
+ int pipefds[2]) {
int flags;
int err;
@@ -238,13 +248,11 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
pipefds[1] = -1;
uv__nonblock(pipefds[0], 1);
- if (container->data.stream->type == UV_NAMED_PIPE &&
- ((uv_pipe_t*)container->data.stream)->ipc)
- flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE;
- else if (writable)
- flags = UV_STREAM_WRITABLE;
- else
- flags = UV_STREAM_READABLE;
+ flags = 0;
+ if (container->flags & UV_WRITABLE_PIPE)
+ flags |= UV_HANDLE_READABLE;
+ if (container->flags & UV_READABLE_PIPE)
+ flags |= UV_HANDLE_WRITABLE;
return uv__stream_open(container->data.stream, pipefds[0], flags);
}
@@ -279,9 +287,20 @@ static void uv__process_child_init(const uv_process_options_t* options,
int stdio_count,
int (*pipes)[2],
int error_fd) {
+ sigset_t set;
int close_fd;
int use_fd;
+ int err;
int fd;
+ int n;
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ int r;
+ int i;
+ int cpumask_size;
+ uv__cpu_set_t cpuset;
+#endif
+#endif
if (options->flags & UV_PROCESS_DETACHED)
setsid();
@@ -296,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
continue;
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
if (pipes[fd][1] == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -315,8 +334,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
close_fd = use_fd;
- if (use_fd == -1) {
- uv__write_int(error_fd, -errno);
+ if (use_fd < 0) {
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -328,7 +347,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
fd = dup2(use_fd, fd);
if (fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -347,7 +366,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if (options->cwd != NULL && chdir(options->cwd)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -363,21 +382,73 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask != NULL) {
+ cpumask_size = uv_cpumask_size();
+ assert(options->cpumask_size >= (size_t)cpumask_size);
+
+ CPU_ZERO(&cpuset);
+ for (i = 0; i < cpumask_size; ++i) {
+ if (options->cpumask[i]) {
+ CPU_SET(i, &cpuset);
+ }
+ }
+
+ r = -pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+ if (r != 0) {
+ uv__write_int(error_fd, r);
+ _exit(127);
+ }
+ }
+#endif
+#endif
+
if (options->env != NULL) {
environ = options->env;
}
+ /* Reset signal disposition. Use a hard-coded limit because NSIG
+ * is not fixed on Linux: it's either 32, 34 or 64, depending on
+ * whether RT signals are enabled. We are not allowed to touch
+ * RT signal handlers, glibc uses them internally.
+ */
+ for (n = 1; n < 32; n += 1) {
+ if (n == SIGKILL || n == SIGSTOP)
+ continue; /* Can't be changed. */
+
+#if defined(__HAIKU__)
+ if (n == SIGKILLTHR)
+ continue; /* Can't be changed. */
+#endif
+
+ if (SIG_ERR != signal(n, SIG_DFL))
+ continue;
+
+ uv__write_int(error_fd, UV__ERR(errno));
+ _exit(127);
+ }
+
+ /* Reset signal mask. */
+ sigemptyset(&set);
+ err = pthread_sigmask(SIG_SETMASK, &set, NULL);
+
+ if (err != 0) {
+ uv__write_int(error_fd, UV__ERR(err));
+ _exit(127);
+ }
+
execvp(options->file, options->args);
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
#endif
@@ -388,9 +459,10 @@ int uv_spawn(uv_loop_t* loop,
const uv_process_options_t* options) {
#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
- return -ENOSYS;
+ return UV_ENOSYS;
#else
int signal_pipe[2] = { -1, -1 };
+ int pipes_storage[8][2];
int (*pipes)[2];
int stdio_count;
ssize_t r;
@@ -400,11 +472,27 @@ int uv_spawn(uv_loop_t* loop,
int i;
int status;
+ if (options->cpumask != NULL) {
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+#else
+ return UV_ENOTSUP;
+#endif
+#else
+ return UV_ENOTSUP;
+#endif
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
+ UV_PROCESS_WINDOWS_HIDE_CONSOLE |
+ UV_PROCESS_WINDOWS_HIDE_GUI |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
@@ -414,8 +502,11 @@ int uv_spawn(uv_loop_t* loop,
if (stdio_count < 3)
stdio_count = 3;
- err = -ENOMEM;
- pipes = uv__malloc(stdio_count * sizeof(*pipes));
+ err = UV_ENOMEM;
+ pipes = pipes_storage;
+ if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
+ pipes = uv__malloc(stdio_count * sizeof(*pipes));
+
if (pipes == NULL)
goto error;
@@ -461,7 +552,7 @@ int uv_spawn(uv_loop_t* loop,
pid = fork();
if (pid == -1) {
- err = -errno;
+ err = UV__ERR(errno);
uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
@@ -501,7 +592,7 @@ int uv_spawn(uv_loop_t* loop,
uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
- err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
+ err = uv__process_open_stream(options->stdio + i, pipes[i]);
if (err == 0)
continue;
@@ -520,7 +611,9 @@ int uv_spawn(uv_loop_t* loop,
process->pid = pid;
process->exit_cb = options->exit_cb;
- uv__free(pipes);
+ if (pipes != pipes_storage)
+ uv__free(pipes);
+
return exec_errorno;
error:
@@ -534,7 +627,9 @@ error:
if (pipes[i][1] != -1)
uv__close_nocheckstdio(pipes[i][1]);
}
- uv__free(pipes);
+
+ if (pipes != pipes_storage)
+ uv__free(pipes);
}
return err;
@@ -549,7 +644,7 @@ int uv_process_kill(uv_process_t* process, int signum) {
int uv_kill(int pid, int signum) {
if (kill(pid, signum))
- return -errno;
+ return UV__ERR(errno);
else
return 0;
}