process_spawn: Return status code (#6075)

This commit is contained in:
Justin M. Keyes
2017-02-09 14:20:24 +01:00
committed by GitHub
parent 3aa8795469
commit 5b8fac8ace
6 changed files with 66 additions and 57 deletions

View File

@@ -33,7 +33,8 @@
# include "os/pty_process_unix.c.generated.h"
#endif
bool pty_process_spawn(PtyProcess *ptyproc)
/// @returns zero on success, or negative error code
int pty_process_spawn(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
static struct termios termios;
@@ -41,6 +42,7 @@ bool pty_process_spawn(PtyProcess *ptyproc)
init_termios(&termios);
}
int status = 0; // zero or negative error code (libuv convention)
Process *proc = (Process *)ptyproc;
assert(!proc->err);
uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD);
@@ -50,8 +52,9 @@ bool pty_process_spawn(PtyProcess *ptyproc)
int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize);
if (pid < 0) {
status = -errno;
ELOG("forkpty failed: %s", strerror(errno));
return false;
return status;
} else if (pid == 0) {
init_child(ptyproc);
abort();
@@ -60,30 +63,34 @@ bool pty_process_spawn(PtyProcess *ptyproc)
// make sure the master file descriptor is non blocking
int master_status_flags = fcntl(master, F_GETFL);
if (master_status_flags == -1) {
status = -errno;
ELOG("Failed to get master descriptor status flags: %s", strerror(errno));
goto error;
}
if (fcntl(master, F_SETFL, master_status_flags | O_NONBLOCK) == -1) {
status = -errno;
ELOG("Failed to make master descriptor non-blocking: %s", strerror(errno));
goto error;
}
if (proc->in && !set_duplicating_descriptor(master, &proc->in->uv.pipe)) {
if (proc->in
&& (status = set_duplicating_descriptor(master, &proc->in->uv.pipe))) {
goto error;
}
if (proc->out && !set_duplicating_descriptor(master, &proc->out->uv.pipe)) {
if (proc->out
&& (status = set_duplicating_descriptor(master, &proc->out->uv.pipe))) {
goto error;
}
ptyproc->tty_fd = master;
proc->pid = pid;
return true;
return 0;
error:
close(master);
kill(pid, SIGKILL);
waitpid(pid, NULL, 0);
return false;
return status;
}
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
@@ -137,9 +144,10 @@ static void init_child(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
return;
}
char *prog = ptyproc->process.argv[0];
setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1);
execvp(ptyproc->process.argv[0], ptyproc->process.argv);
fprintf(stderr, "execvp failed: %s\n", strerror(errno));
execvp(prog, ptyproc->process.argv);
fprintf(stderr, "execvp failed: %s: %s\n", strerror(errno), prog);
}
static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL
@@ -197,22 +205,24 @@ static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL
termios->c_cc[VTIME] = 0;
}
static bool set_duplicating_descriptor(int fd, uv_pipe_t *pipe)
static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe)
FUNC_ATTR_NONNULL_ALL
{
int status = 0; // zero or negative error code (libuv convention)
int fd_dup = dup(fd);
if (fd_dup < 0) {
status = -errno;
ELOG("Failed to dup descriptor %d: %s", fd, strerror(errno));
return false;
return status;
}
int uv_result = uv_pipe_open(pipe, fd_dup);
if (uv_result) {
status = uv_pipe_open(pipe, fd_dup);
if (status) {
ELOG("Failed to set pipe to descriptor %d: %s",
fd_dup, uv_strerror(uv_result));
fd_dup, uv_strerror(status));
close(fd_dup);
return false;
return status;
}
return true;
return status;
}
static void chld_handler(uv_signal_t *handle, int signum)