Skip to content

Commit

Permalink
Rename uv_spawn() to program_spawn().
Browse files Browse the repository at this point in the history
The current name is annoying, as it is a name that is also used by libuv
officially, even though the semantics are different. It also makes it
harder to implement <program.h> on non-CloudABI systems to act as a
launcher for CloudABI processes.

Simply add this function to <program.h>, so it can be next to all of the
other CloudABI specific program management functions.
  • Loading branch information
EdSchouten committed Nov 8, 2017
1 parent 4802cdf commit be372af
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 76 deletions.
8 changes: 7 additions & 1 deletion src/include/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,23 @@
#ifndef _PROGRAM_H_
#define _PROGRAM_H_

#include <_/cdefs.h>
#include <_/types.h>

#ifndef argdata_t
typedef struct argdata_t argdata_t;
#define argdata_t argdata_t
#endif

struct uv_loop_s;
struct uv_process_s;

__BEGIN_DECLS
int program_exec(int, const argdata_t *);
const char *program_getpid(void);
_Noreturn void program_main(const argdata_t *);
int program_spawn(struct uv_loop_s *, struct uv_process_s *, int,
const argdata_t *,
void (*)(struct uv_process_s *, __int64_t, int));
__END_DECLS

// TODO(ed): Remove the deprecated features below.
Expand Down
23 changes: 4 additions & 19 deletions src/include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@

// <uv.h> - event loops
//
// Extensions:
// - uv_process_options_t::argdata and uv_process_options_t::executable:
// Allows for spawning of subprocesses similar to <program.h>'s
// program_exec().
//
// Features missing:
// - UV_CONNECT, UV_UDP_IPV6ONLY, UV_UDP_REUSEADDR, UV_UDP_SEND,
// uv_connect_cb, uv_connect_t, uv_connection_cb, uv_membership,
Expand Down Expand Up @@ -69,14 +64,11 @@
// avoid to improve thread safety.
// - uv_lib_t, uv_dlclose(), uv_dlerror(), uv_dlopen() and uv_dlsym():
// This environment does not support loading libraries dynamically.
// - uv_process_flags, uv_process_options_t::args,
// uv_process_options_t::cwd, uv_process_options_t::env,
// uv_process_options_t::file, uv_process_options_t::flags,
// uv_process_options_t::gid, uv_process_options_t::stdio,
// uv_process_options_t::stdio_count, uv_process_options_t::uid,
// uv_stdio_container_t and uv_stdio_flags:
// - uv_process_flags, uv_process_options_t, uv_stdio_container_t,
// uv_stdio_flags and uv_spawn():
// Launching unsandboxed processes is unsupported, as this would
// circumvent this environment's security framework.
// circumvent this environment's security framework. Use <program.h>'s
// program_spawn() instead.
// - uv_process_t::pid and uv_kill():
// Global process namespace cannot be accessed.
// - uv_tty_mode_t, uv_tty_set_mode() and uv_tty_get_winsize():
Expand Down Expand Up @@ -702,16 +694,9 @@ struct uv_process_s {
struct __uv_active_processes_entry __uv_active_processes_entry;
};

typedef struct uv_process_options_s {
uv_exit_cb exit_cb;
uv_file executable;
const argdata_t *argdata;
} uv_process_options_t;

__BEGIN_DECLS
void uv_disable_stdio_inheritance(void);
int uv_process_kill(uv_process_t *, int);
int uv_spawn(uv_loop_t *, uv_process_t *, const uv_process_options_t *);
__END_DECLS

//
Expand Down
28 changes: 14 additions & 14 deletions src/libc/uv/uv_spawn.c → src/libc/program/program_spawn.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@
// See the LICENSE file for details.

#include <common/errno.h>
#include <common/uv.h>

#include <argdata.h>
#include <cloudabi_syscalls.h>
#include <errno.h>
#include <program.h>
#include <stdlib.h>
#include <uv.h>

#include <common/uv.h>

int uv_spawn(uv_loop_t *loop, uv_process_t *handle,
const uv_process_options_t *options) {
int program_spawn(uv_loop_t *loop, uv_process_t *handle, int fd,
const argdata_t *ad, uv_exit_cb cb) {
// Serialize the argument data.
size_t datalen;
size_t fdslen;
argdata_serialized_length(options->argdata, &datalen, &fdslen);
argdata_serialized_length(ad, &datalen, &fdslen);
int *fds = malloc(fdslen * sizeof(int) + datalen);
if (fds == NULL)
return UV_ENOMEM;
return ENOMEM;
char *data = (char *)&fds[fdslen];
fdslen = argdata_serialize(options->argdata, data, fds);
fdslen = argdata_serialize(ad, data, fds);

// Create a pipe to send proc_exec()'s error code back to the parent.
cloudabi_fd_t error_read_fd, error_write_fd;
Expand All @@ -31,7 +32,7 @@ int uv_spawn(uv_loop_t *loop, uv_process_t *handle,
CLOUDABI_FILETYPE_SOCKET_STREAM, &error_read_fd, &error_write_fd);
if (error != 0) {
free(fds);
return -error;
return error;
}
}

Expand All @@ -44,17 +45,16 @@ int uv_spawn(uv_loop_t *loop, uv_process_t *handle,
free(fds);
cloudabi_sys_fd_close(error_read_fd);
cloudabi_sys_fd_close(error_write_fd);
return -error;
return error;
}
}

// In the child process, attempt to execute. If that fails, write the
// error code into the pipe.
if (process_fd == CLOUDABI_PROCESS_CHILD) {
cloudabi_errno_t error = errno_fixup_executable(
options->executable,
cloudabi_sys_proc_exec(options->executable, data, datalen,
(cloudabi_fd_t *)fds, fdslen));
fd, cloudabi_sys_proc_exec(fd, data, datalen, (cloudabi_fd_t *)fds,
fdslen));
cloudabi_ciovec_t error_buf = {.buf = &error, .buf_len = sizeof(error)};
size_t nwritten;
cloudabi_sys_fd_write(error_write_fd, &error_buf, 1, &nwritten);
Expand All @@ -74,15 +74,15 @@ int uv_spawn(uv_loop_t *loop, uv_process_t *handle,
cloudabi_sys_fd_close(error_read_fd);
if (error == 0 && nread == sizeof(exec_error) && exec_error != 0) {
cloudabi_sys_fd_close(process_fd);
return -exec_error;
return exec_error;
}
}

// Program spawned successfully.
__uv_handle_init(loop, (uv_handle_t *)handle, UV_PROCESS);
__uv_handle_start((uv_handle_t *)handle);
__uv_active_processes_insert_last(&loop->__active_processes, handle);
handle->__cb = options->exit_cb;
handle->__cb = cb;
handle->__fd = process_fd;
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <argdata.h>
#include <errno.h>
#include <fcntl.h>
#include <program.h>
#include <signal.h>
#include <stdbool.h>
#include <testing.h>
Expand All @@ -20,58 +21,45 @@ static void unused_cb(uv_process_t *handle, int64_t exit_status,
ASSERT_TRUE(false);
}

TEST(uv_spawn, eacces) {
TEST(program_spawn, eacces) {
uv_loop_t loop;
ASSERT_EQ(0, uv_loop_init(&loop));

// Attempt to execute a directory file descriptor.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = unused_cb,
.executable = fd_tmp,
.argdata = &argdata_null,
};
ASSERT_EQ(UV_EACCES, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(EACCES,
program_spawn(&loop, &handle, fd_tmp, &argdata_null, unused_cb));

ASSERT_EQ(0, uv_loop_close(&loop));
}

TEST(uv_spawn, ebadf1) {
TEST(program_spawn, ebadf1) {
uv_loop_t loop;
ASSERT_EQ(0, uv_loop_init(&loop));

// Invalid file descriptor number.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = unused_cb,
.executable = -1,
.argdata = &argdata_null,
};
ASSERT_EQ(UV_EBADF, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(EBADF, program_spawn(&loop, &handle, -1, &argdata_null, unused_cb));

ASSERT_EQ(0, uv_loop_close(&loop));
}

TEST(uv_spawn, ebadf2) {
TEST(program_spawn, ebadf2) {
int executable = openat(fd_tmp, "Hello", O_CREAT | O_WRONLY);
ASSERT_LE(0, executable);
uv_loop_t loop;
ASSERT_EQ(0, uv_loop_init(&loop));

// Executable is not open for executing.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = unused_cb,
.executable = executable,
.argdata = &argdata_null,
};
ASSERT_EQ(UV_EBADF, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(EBADF, program_spawn(&loop, &handle, executable, &argdata_null,
unused_cb));
ASSERT_EQ(0, close(executable));

ASSERT_EQ(0, uv_loop_close(&loop));
}

TEST(uv_spawn, enoexec) {
TEST(program_spawn, enoexec) {
// Create an empty file.
int executable = openat(fd_tmp, "Hello", O_CREAT | O_WRONLY);
ASSERT_LE(0, executable);
Expand All @@ -84,12 +72,8 @@ TEST(uv_spawn, enoexec) {

// Unsupported file format.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = unused_cb,
.executable = executable,
.argdata = &argdata_null,
};
ASSERT_EQ(-ENOEXEC, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(ENOEXEC, program_spawn(&loop, &handle, executable, &argdata_null,
unused_cb));
ASSERT_EQ(0, close(executable));

ASSERT_EQ(0, uv_loop_close(&loop));
Expand Down Expand Up @@ -157,7 +141,7 @@ static void close_cb(uv_handle_t *handle) {
*(bool *)handle->data = true;
}

TEST(uv_spawn, sigfpe) {
TEST(program_spawn, sigfpe) {
// Create our faulty executable.
int executable = openat(fd_tmp, "Crash", O_CREAT | O_WRONLY);
ASSERT_LE(0, executable);
Expand All @@ -172,12 +156,8 @@ TEST(uv_spawn, sigfpe) {

// Execution should succeed.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = crash_result,
.executable = executable,
.argdata = &argdata_null,
};
ASSERT_EQ(0, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(0, program_spawn(&loop, &handle, executable, &argdata_null,
crash_result));
ASSERT_EQ(0, close(executable));

// Let the process run until termination.
Expand Down
2 changes: 1 addition & 1 deletion src/libc/symbols
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ preadv
program_exec
program_getpid
program_main
program_spawn
program_spawn_deprecated
program_wait_deprecated
pselect
Expand Down Expand Up @@ -1018,7 +1019,6 @@ uv_sem_post
uv_sem_trywait
uv_sem_wait
uv_shutdown
uv_spawn
uv_stop
uv_stream_set_blocking
uv_strerror
Expand Down
9 changes: 3 additions & 6 deletions src/libc/uv/uv_process_kill_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <argdata.h>
#include <fcntl.h>
#include <program.h>
#include <signal.h>
#include <testing.h>
#include <unistd.h>
Expand Down Expand Up @@ -86,12 +87,8 @@ TEST(uv_process_kill, example) {

// Execution should succeed.
uv_process_t handle;
uv_process_options_t options = {
.exit_cb = kill_result,
.executable = executable,
.argdata = &argdata_null,
};
ASSERT_EQ(0, uv_spawn(&loop, &handle, &options));
ASSERT_EQ(
0, program_spawn(&loop, &handle, executable, &argdata_null, kill_result));
ASSERT_EQ(0, close(executable));

// No termination should be observed.
Expand Down

0 comments on commit be372af

Please sign in to comment.