include: uv_spawn takes const uv_process_options_t*

Passing or returning structs as values makes life hard for people that
work with libuv through a foreign function interface. Switch to a
pointer-based approach.

Fixes #684.
This commit is contained in:
Ben Noordhuis 2013-09-01 08:20:15 +02:00
parent 263da51967
commit 8c6ea10502
10 changed files with 84 additions and 79 deletions

View File

@ -1502,8 +1502,9 @@ struct uv_process_s {
};
/* Initializes uv_process_t and starts the process. */
UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*,
uv_process_options_t options);
UV_EXTERN int uv_spawn(uv_loop_t* loop,
uv_process_t* handle,
const uv_process_options_t* options);
/*

View File

@ -183,7 +183,7 @@ skip:
/*
* Used for initializing stdio streams like options.stdin_stream. Returns
* Used for initializing stdio streams like options->stdin_stream. Returns
* zero on success.
*/
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
@ -270,7 +270,7 @@ static void uv__write_int(int fd, int val) {
}
static void uv__process_child_init(uv_process_options_t options,
static void uv__process_child_init(const uv_process_options_t* options,
int stdio_count,
int (*pipes)[2],
int error_fd) {
@ -278,7 +278,7 @@ static void uv__process_child_init(uv_process_options_t options,
int use_fd;
int fd;
if (options.flags & UV_PROCESS_DETACHED)
if (options->flags & UV_PROCESS_DETACHED)
setsid();
for (fd = 0; fd < stdio_count; fd++) {
@ -313,29 +313,29 @@ static void uv__process_child_init(uv_process_options_t options,
uv__nonblock(fd, 0);
}
if (options.cwd && chdir(options.cwd)) {
if (options->cwd != NULL && chdir(options->cwd)) {
uv__write_int(error_fd, -errno);
perror("chdir()");
_exit(127);
}
if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
uv__write_int(error_fd, -errno);
perror("setgid()");
_exit(127);
}
if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
uv__write_int(error_fd, -errno);
perror("setuid()");
_exit(127);
}
if (options.env) {
environ = options.env;
if (options->env != NULL) {
environ = options->env;
}
execvp(options.file, options.args);
execvp(options->file, options->args);
uv__write_int(error_fd, -errno);
perror("execvp()");
_exit(127);
@ -344,7 +344,7 @@ static void uv__process_child_init(uv_process_options_t options,
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,
const uv_process_options_t options) {
const uv_process_options_t* options) {
int signal_pipe[2] = { -1, -1 };
int (*pipes)[2];
int stdio_count;
@ -354,17 +354,17 @@ int uv_spawn(uv_loop_t* loop,
int err;
int i;
assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
QUEUE_INIT(&process->queue);
stdio_count = options.stdio_count;
stdio_count = options->stdio_count;
if (stdio_count < 3)
stdio_count = 3;
@ -378,8 +378,8 @@ int uv_spawn(uv_loop_t* loop,
pipes[i][1] = -1;
}
for (i = 0; i < options.stdio_count; i++) {
err = uv__process_init_stdio(options.stdio + i, pipes[i]);
for (i = 0; i < options->stdio_count; i++) {
err = uv__process_init_stdio(options->stdio + i, pipes[i]);
if (err)
goto error;
}
@ -442,13 +442,13 @@ int uv_spawn(uv_loop_t* loop,
close(signal_pipe[0]);
for (i = 0; i < options.stdio_count; i++) {
err = uv__process_open_stream(options.stdio + i, pipes[i], i == 0);
for (i = 0; i < options->stdio_count; i++) {
err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
if (err == 0)
continue;
while (i--)
uv__process_close_stream(options.stdio + i);
uv__process_close_stream(options->stdio + i);
goto error;
}
@ -457,7 +457,7 @@ int uv_spawn(uv_loop_t* loop,
QUEUE_INSERT_TAIL(q, &process->queue);
process->pid = pid;
process->exit_cb = options.exit_cb;
process->exit_cb = options->exit_cb;
uv__handle_start(process);
free(pipes);

View File

@ -311,8 +311,9 @@ void uv_fatal_error(const int errorno, const char* syscall);
/*
* Process stdio handles.
*/
int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
BYTE** buffer_ptr);
int uv__stdio_create(uv_loop_t* loop,
const uv_process_options_t* options,
BYTE** buffer_ptr);
void uv__stdio_destroy(BYTE* buffer);
void uv__stdio_noinherit(BYTE* buffer);
int uv__stdio_verify(BYTE* buffer, WORD size);

View File

@ -260,8 +260,9 @@ int uv__create_nul_handle(HANDLE* handle_ptr,
}
int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
BYTE** buffer_ptr) {
int uv__stdio_create(uv_loop_t* loop,
const uv_process_options_t* options,
BYTE** buffer_ptr) {
BYTE* buffer;
int count, i;
int err;

View File

@ -802,8 +802,9 @@ void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
}
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv_process_options_t options) {
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,
const uv_process_options_t* options) {
int i;
int err = 0;
WCHAR* path = NULL;
@ -814,44 +815,45 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
PROCESS_INFORMATION info;
DWORD process_flags;
if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
return UV_ENOTSUP;
}
if (options.file == NULL ||
options.args == NULL) {
if (options->file == NULL ||
options->args == NULL) {
return UV_EINVAL;
}
assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
uv_process_init(loop, process);
process->exit_cb = options.exit_cb;
process->exit_cb = options->exit_cb;
err = uv_utf8_to_utf16_alloc(options.file, &application);
err = uv_utf8_to_utf16_alloc(options->file, &application);
if (err)
goto immediate_failure;
err = make_program_args(options.args,
options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
&arguments);
err = make_program_args(
options->args,
options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
&arguments);
if (err)
goto immediate_failure;
if (options.env) {
err = make_program_env(options.env, &env);
if (options->env) {
err = make_program_env(options->env, &env);
if (err)
goto immediate_failure;
}
if (options.cwd) {
if (options->cwd) {
/* Explicit cwd */
err = uv_utf8_to_utf16_alloc(options.cwd, &cwd);
err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);
if (err)
goto immediate_failure;
@ -901,7 +903,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
}
}
err = uv__stdio_create(loop, &options, &process->child_stdio_buffer);
err = uv__stdio_create(loop, options, &process->child_stdio_buffer);
if (err)
goto immediate_failure;
@ -929,7 +931,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
if (options.flags & UV_PROCESS_WINDOWS_HIDE) {
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
} else {
@ -938,7 +940,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
process_flags = CREATE_UNICODE_ENVIRONMENT;
if (options.flags & UV_PROCESS_DETACHED) {
if (options->flags & UV_PROCESS_DETACHED) {
/* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
* means that libuv might not let you create a fully deamonized process
* when run under job control. However the type of job control that libuv
@ -968,7 +970,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
/* If the process isn't spawned as detached, assign to the global job */
/* object so windows will kill it when the parent process dies. */
if (!(options.flags & UV_PROCESS_DETACHED)) {
if (!(options->flags & UV_PROCESS_DETACHED)) {
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
@ -989,8 +991,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
}
/* Set IPC pid to all IPC pipes. */
for (i = 0; i < options.stdio_count; i++) {
const uv_stdio_container_t* fdopt = &options.stdio[i];
for (i = 0; i < options->stdio_count; i++) {
const uv_stdio_container_t* fdopt = &options->stdio[i];
if (fdopt->flags & UV_CREATE_PIPE &&
fdopt->data.stream->type == UV_NAMED_PIPE &&
((uv_pipe_t*) fdopt->data.stream)->ipc) {

View File

@ -122,7 +122,7 @@ static void spawn(void) {
options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
options.stdio[1].data.stream = (uv_stream_t*)&out;
r = uv_spawn(loop, &process, options);
r = uv_spawn(loop, &process, &options);
ASSERT(r == 0);
process_open = 1;

View File

@ -234,7 +234,7 @@ void spawn_helper(uv_pipe_t* channel,
options.stdio[0].data.stream = (uv_stream_t*)channel;
options.stdio_count = 1;
r = uv_spawn(uv_default_loop(), process, options);
r = uv_spawn(uv_default_loop(), process, &options);
ASSERT(r == 0);
}

View File

@ -403,7 +403,7 @@ TEST_IMPL(process_ref) {
options.args = argv;
options.exit_cb = NULL;
r = uv_spawn(uv_default_loop(), &h, options);
r = uv_spawn(uv_default_loop(), &h, &options);
ASSERT(r == 0);
uv_unref((uv_handle_t*)&h);

View File

@ -166,7 +166,7 @@ static void timer_cb(uv_timer_t* handle, int status) {
TEST_IMPL(spawn_fails) {
init_process_options("", exit_cb_expect_enoent);
options.file = options.args[0] = "program-that-had-better-not-exist";
ASSERT(0 == uv_spawn(uv_default_loop(), &process, options));
ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
ASSERT(0 != uv_is_active((uv_handle_t*)&process));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(1 == exit_cb_called);
@ -181,7 +181,7 @@ TEST_IMPL(spawn_exit_code) {
init_process_options("spawn_helper1", exit_cb);
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -209,7 +209,7 @@ TEST_IMPL(spawn_stdout) {
options.stdio[1].data.stream = (uv_stream_t*)&out;
options.stdio_count = 2;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
@ -252,7 +252,7 @@ TEST_IMPL(spawn_stdout_to_file) {
options.stdio[1].data.fd = file;
options.stdio_count = 2;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -301,7 +301,7 @@ TEST_IMPL(spawn_stdin) {
options.stdio[1].data.stream = (uv_stream_t*)&out;
options.stdio_count = 2;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
buf.base = buffer;
@ -340,7 +340,7 @@ TEST_IMPL(spawn_stdio_greater_than_3) {
options.stdio[3].data.stream = (uv_stream_t*)&pipe;
options.stdio_count = 4;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read);
@ -367,7 +367,7 @@ TEST_IMPL(spawn_ignored_stdio) {
options.stdio = NULL;
options.stdio_count = 0;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -386,7 +386,7 @@ TEST_IMPL(spawn_and_kill) {
init_process_options("spawn_helper4", kill_cb);
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_timer_init(uv_default_loop(), &timer);
@ -426,7 +426,7 @@ TEST_IMPL(spawn_preserve_env) {
/* Explicitly set options.env to NULL to test for env clobbering. */
options.env = NULL;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
@ -453,7 +453,7 @@ TEST_IMPL(spawn_detached) {
options.flags |= UV_PROCESS_DETACHED;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
uv_unref((uv_handle_t*)&process);
@ -502,7 +502,7 @@ TEST_IMPL(spawn_and_kill_with_std) {
options.stdio[2].data.stream = (uv_stream_t*)&err;
options.stdio_count = 3;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
buf = uv_buf_init(message, sizeof message);
@ -551,7 +551,7 @@ TEST_IMPL(spawn_and_ping) {
options.stdio[1].data.stream = (uv_stream_t*)&out;
options.stdio_count = 2;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
/* Sending signum == 0 should check if the
@ -588,7 +588,7 @@ TEST_IMPL(kill) {
init_process_options("spawn_helper4", kill_cb);
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
/* Sending signum == 0 should check if the
@ -641,7 +641,7 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
NULL);
ASSERT(pipe_handle != INVALID_HANDLE_VALUE);
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
@ -806,7 +806,7 @@ TEST_IMPL(spawn_setuid_setgid) {
options.gid = pw->pw_gid;
options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -840,7 +840,7 @@ TEST_IMPL(spawn_setuid_fails) {
options.flags |= UV_PROCESS_SETUID;
options.uid = 0;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -872,7 +872,7 @@ TEST_IMPL(spawn_setgid_fails) {
options.flags |= UV_PROCESS_SETGID;
options.gid = 0;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -904,7 +904,7 @@ TEST_IMPL(spawn_setuid_fails) {
options.flags |= UV_PROCESS_SETUID;
options.uid = (uv_uid_t) -42424242;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == UV_ENOTSUP);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -925,7 +925,7 @@ TEST_IMPL(spawn_setgid_fails) {
options.flags |= UV_PROCESS_SETGID;
options.gid = (uv_gid_t) -42424242;
r = uv_spawn(uv_default_loop(), &process, options);
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == UV_ENOTSUP);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
@ -941,7 +941,7 @@ TEST_IMPL(spawn_setgid_fails) {
TEST_IMPL(spawn_auto_unref) {
init_process_options("spawn_helper1", NULL);
ASSERT(0 == uv_spawn(uv_default_loop(), &process, options));
ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(0 == uv_is_closing((uv_handle_t*) &process));
uv_close((uv_handle_t*) &process, NULL);

View File

@ -136,7 +136,7 @@ TEST_IMPL(stdio_over_pipes) {
options.stdio[1].data.stream = (uv_stream_t*)&out;
options.stdio_count = 2;
r = uv_spawn(loop, &process, options);
r = uv_spawn(loop, &process, &options);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);