Skip to content

Commit

Permalink
Close FILE structs after forking
Browse files Browse the repository at this point in the history
Fixes #48
  • Loading branch information
emersion committed Nov 7, 2018
1 parent 14e90a9 commit 51c7fe8
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 5 deletions.
2 changes: 1 addition & 1 deletion shell/task/assignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static int task_assignment_poll(struct task *task, struct context *ctx) {
free(new_value);
}

return 0;
return EXIT_SUCCESS;
}

static const struct task_interface task_assignment_impl = {
Expand Down
9 changes: 7 additions & 2 deletions shell/task/async.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ static void task_async_destroy(struct task *task) {
free(ta);
}

static int fork_detached(void) {
static int fork_detached(struct context *ctx) {
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "failed to fork(): %s\n", strerror(errno));
return -1;
} else if (pid == 0) {
// On exit, libc cleans up FILE structs, and can seek the backing FD if
// some data has been buffered. This messes up the parent's FD too. To
// prevent this from hapening, close all FILE structs.
fclose(ctx->state->input);

pid_t child_pid = fork();
if (child_pid < 0) {
fprintf(stderr, "failed to fork(): %s\n", strerror(errno));
Expand All @@ -50,7 +55,7 @@ static bool task_async_start(struct task *task, struct context *ctx) {
struct task_async *ta = (struct task_async *)task;

// Start a subshell
int ret = fork_detached();
int ret = fork_detached(ctx);
if (ret < 0) {
return false;
} else if (ret == 0) {
Expand Down
5 changes: 5 additions & 0 deletions shell/task/command_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ static bool task_process_start(struct task_command *tc, struct context *ctx) {
fprintf(stderr, "failed to fork(): %s\n", strerror(errno));
return false;
} else if (pid == 0) {
// On exit, libc cleans up FILE structs, and can seek the backing FD if
// some data has been buffered. This messes up the parent's FD too. To
// prevent this from hapening, close all FILE structs.
fclose(ctx->state->input);

for (size_t i = 0; i < sc->assignments.len; ++i) {
struct mrsh_assignment *assign = sc->assignments.data[i];
uint32_t prev_attribs;
Expand Down
5 changes: 5 additions & 0 deletions shell/task/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ static bool task_subshell_start(struct task_subshell *ts, struct context *ctx) {
fprintf(stderr, "failed to fork(): %s\n", strerror(errno));
return false;
} else if (pid == 0) {
// On exit, libc cleans up FILE structs, and can seek the backing FD if
// some data has been buffered. This messes up the parent's FD too. To
// prevent this from hapening, close all FILE structs.
fclose(ctx->state->input);

errno = 0;
int ret = task_run(ts->subtask, ctx);
if (ret < 0) {
Expand Down
10 changes: 8 additions & 2 deletions shell/task/word.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct task_word {

static bool read_full(int fd, char *buf, size_t size) {
size_t n_read = 0;
do {
while (n_read < size) {
ssize_t n = read(fd, buf, size - n_read);
if (n < 0 && errno == EINTR) {
continue;
Expand All @@ -39,7 +39,7 @@ static bool read_full(int fd, char *buf, size_t size) {
return false;
}
n_read += n;
} while (n_read < size);
}
return true;
}

Expand All @@ -66,7 +66,13 @@ static bool task_word_command_start(struct task_word *tt,
fprintf(stderr, "failed to fork(): %s\n", strerror(errno));
return false;
} else if (pid == 0) {
// On exit, libc cleans up FILE structs, and can seek the backing FD if
// some data has been buffered. This messes up the parent's FD too. To
// prevent this from hapening, close all FILE structs.
fclose(ctx->state->input);

dup2(fd, STDOUT_FILENO);
close(fd);

if (ctx->stdin_fileno >= 0) {
close(ctx->stdin_fileno);
Expand Down

0 comments on commit 51c7fe8

Please sign in to comment.