-
Notifications
You must be signed in to change notification settings - Fork 129
Call chdir to change working directory in older versions of glibc #449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,10 @@ | |
#endif | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <sys/wait.h> | ||
|
||
#include "process.h" | ||
|
||
|
@@ -32,4 +36,61 @@ bool SPM_posix_spawn_file_actions_addchdir_np_supported() { | |
#endif | ||
} | ||
|
||
int SPM_fork_exec_chdir(pid_t *pid, const char *cwd, | ||
const char *cmd, char *const argv[], char *const envp[], | ||
int in_pipe[], int out_pipe[], int err_pipe[], bool redirect_out, bool redirect_err) { | ||
*pid = fork(); | ||
|
||
if (*pid < 0) { | ||
perror("fork() failed"); | ||
_exit(EXIT_FAILURE); | ||
} else if (*pid > 0) { // Parent process | ||
// Wait for child process to finish | ||
int status; | ||
waitpid(*pid, &status, 0); | ||
return status; | ||
} else { // Child process | ||
// Change working directory then execute cmd | ||
if (chdir(cwd)) { | ||
_exit(EXIT_FAILURE); | ||
} | ||
|
||
// Replicate pipe logic in TSCBasic.Process.launch() | ||
|
||
// Dupe the read portion of the remote to 0. | ||
dup2(in_pipe[0], 0); | ||
// Close the other side's pipe since it was duped to 0. | ||
close(in_pipe[0]); | ||
close(in_pipe[1]); | ||
|
||
if (redirect_out) { | ||
// Open the write end of the pipe. | ||
dup2(out_pipe[1], 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. who's reading that pipe? It appears like the parent waits for the child to complete and then reads those pipes. That's a deadlock. The child will fill up the pipe until it's full (assuming the child writes enough). And then the child will block until something reads from that pipe. So the child won't exit but the parent will wait for it to exit: child waits for parent to read <-> parent waits for child to exit |
||
// Close the other ends of the pipe since they were duped to 1. | ||
close(out_pipe[0]); | ||
close(out_pipe[1]); | ||
|
||
if (redirect_err) { | ||
// If merged was requested, send stderr to stdout. | ||
dup2(1, 2); | ||
} else { | ||
// If no redirect was requested, open the pipe for stderr. | ||
dup2(err_pipe[1], 2); | ||
// Close the other ends of the pipe since they were dupped to 2. | ||
close(err_pipe[0]); | ||
close(err_pipe[1]); | ||
} | ||
} else { | ||
dup2(1, 1); | ||
dup2(2, 2); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there are a bunch of things missing here:
|
||
execve(cmd, argv, envp); | ||
|
||
// If execve returns, it must have failed. | ||
perror(cmd); | ||
_exit(EXIT_FAILURE); | ||
} | ||
} | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is suspicious: usually the parent needs to read from the stdout & stderr pipes it passed into the child. If not, the child will block if it writes more than the pipe has space for (usually somewhere between 8 and 128 kiB).