fix: exec() error not returned to parent (#1363)
* fix: exec() error not returned to parent * chore: remove accidental lua.h inclusion
This commit is contained in:
parent
b634b61866
commit
ab3d6004a1
|
@ -293,6 +293,7 @@ static int process_start(lua_State* L) {
|
||||||
CloseHandle(self->process_information.hProcess);
|
CloseHandle(self->process_information.hProcess);
|
||||||
CloseHandle(self->process_information.hThread);
|
CloseHandle(self->process_information.hThread);
|
||||||
#else
|
#else
|
||||||
|
int control_pipe[2] = { 0 };
|
||||||
for (int i = 0; i < 3; ++i) { // Make only the parents fd's non-blocking. Children should block.
|
for (int i = 0; i < 3; ++i) { // Make only the parents fd's non-blocking. Children should block.
|
||||||
if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1) {
|
if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1) {
|
||||||
lua_pushfstring(L, "Error creating pipes: %s", strerror(errno));
|
lua_pushfstring(L, "Error creating pipes: %s", strerror(errno));
|
||||||
|
@ -300,12 +301,25 @@ static int process_start(lua_State* L) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// create a pipe to get the exit code of exec()
|
||||||
|
if (pipe(control_pipe) == -1) {
|
||||||
|
lua_pushfstring(L, "Error creating control pipe: %s", strerror(errno));
|
||||||
|
retval = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (fcntl(control_pipe[1], F_SETFD, FD_CLOEXEC) == -1) {
|
||||||
|
lua_pushfstring(L, "Error setting FD_CLOEXEC: %s", strerror(errno));
|
||||||
|
retval = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
self->pid = (long)fork();
|
self->pid = (long)fork();
|
||||||
if (self->pid < 0) {
|
if (self->pid < 0) {
|
||||||
lua_pushfstring(L, "Error running fork: %s.", strerror(errno));
|
lua_pushfstring(L, "Error running fork: %s.", strerror(errno));
|
||||||
retval = -1;
|
retval = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (!self->pid) {
|
} else if (!self->pid) {
|
||||||
|
// child process
|
||||||
if (!detach)
|
if (!detach)
|
||||||
setpgid(0,0);
|
setpgid(0,0);
|
||||||
for (int stream = 0; stream < 3; ++stream) {
|
for (int stream = 0; stream < 3; ++stream) {
|
||||||
|
@ -320,12 +334,39 @@ static int process_start(lua_State* L) {
|
||||||
for (set = 0; set < env_len && setenv(env_names[set], env_values[set], 1) == 0; ++set);
|
for (set = 0; set < env_len && setenv(env_names[set], env_values[set], 1) == 0; ++set);
|
||||||
if (set == env_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1))
|
if (set == env_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1))
|
||||||
execvp(cmd[0], (char** const)cmd);
|
execvp(cmd[0], (char** const)cmd);
|
||||||
const char* msg = strerror(errno);
|
write(control_pipe[1], &errno, sizeof(errno));
|
||||||
size_t result = write(STDERR_FD, msg, strlen(msg)+1);
|
_exit(-1);
|
||||||
_exit(result == strlen(msg)+1 ? -1 : -2);
|
|
||||||
}
|
}
|
||||||
|
// close our write side so we can read from child
|
||||||
|
close(control_pipe[1]);
|
||||||
|
control_pipe[1] = 0;
|
||||||
|
|
||||||
|
// wait for child process to respond
|
||||||
|
int sz, process_rc;
|
||||||
|
while ((sz = read(control_pipe[0], &process_rc, sizeof(int))) == -1) {
|
||||||
|
if (errno == EPIPE) break;
|
||||||
|
if (errno != EINTR) {
|
||||||
|
lua_pushfstring(L, "Error getting child process status: %s", strerror(errno));
|
||||||
|
retval = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz) {
|
||||||
|
// read something from pipe; exec failed
|
||||||
|
int status;
|
||||||
|
waitpid(self->pid, &status, 0);
|
||||||
|
lua_pushfstring(L, "Error creating child process: %s", strerror(process_rc));
|
||||||
|
retval = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
cleanup:
|
cleanup:
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (control_pipe[0]) close(control_pipe[0]);
|
||||||
|
if (control_pipe[1]) close(control_pipe[1]);
|
||||||
|
#endif
|
||||||
for (size_t i = 0; i < env_len; ++i) {
|
for (size_t i = 0; i < env_len; ++i) {
|
||||||
free((char*)env_names[i]);
|
free((char*)env_names[i]);
|
||||||
free((char*)env_values[i]);
|
free((char*)env_values[i]);
|
||||||
|
|
Loading…
Reference in New Issue