Skip to content

Commit f13e925

Browse files
committed
Fix pipe redirection bugs on Linux.
1 parent 3b67627 commit f13e925

File tree

1 file changed

+43
-59
lines changed

1 file changed

+43
-59
lines changed

runtime/process-posix.c

+43-59
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static void update_all_child_statuses () {
155155
//NOTE: curr->next is retrieved preemptively because
156156
//update_child_status may call free() on curr, and make
157157
//curr->next inaccessible.
158-
ChildProcessList* next = curr->next;
158+
volatile ChildProcessList* next = curr->next;
159159
update_child_status(curr->proc->pid);
160160
curr = next;
161161
}
@@ -458,28 +458,24 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
458458
stz_int output, stz_int error,
459459
stz_byte* working_dir, stz_byte** env_vars, Process* process) {
460460

461-
//Compute pipe sources. Examples of entries:
462-
// pipe_sources[PROCESS_IN] = 0, indicates that
463-
// the input pipe to the process is served by POSIX file descriptor 0 (stdin).
464-
// pipe_sources[PROCESS_IN] = -1, indicates that
465-
// no input pipe to the process should be created.
466-
// pipe_sources[STANDARD_ERR] = 1, indicates that
467-
// the process standard error stream should be served by POSIX file descriptor 1 (stdout),
468-
// which means child writes to its error stream should automatically go to stdout.
469-
int pipe_sources[NUM_STREAM_SPECS];
461+
//Compute which pipes to create for the process.
462+
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
463+
//needs to be created.
464+
int has_pipes[NUM_STREAM_SPECS];
470465
for(int i=0; i<NUM_STREAM_SPECS; i++)
471-
pipe_sources[i] = -1;
472-
pipe_sources[input] = 0;
473-
pipe_sources[output] = 1;
474-
pipe_sources[error] = 2;
466+
has_pipes[i] = 0;
467+
has_pipes[input] = 1;
468+
has_pipes[output] = 1;
469+
has_pipes[error] = 1;
470+
has_pipes[STANDARD_IN] = 0;
471+
has_pipes[STANDARD_OUT] = 0;
472+
has_pipes[STANDARD_ERR] = 0;
475473

476474
//Generate pipes for PROCESS_IN, PROCESS_OUT, PROCESS_ERR.
477475
int pipes[NUM_STREAM_SPECS][2];
478-
int process_io[] = {PROCESS_IN, PROCESS_OUT, PROCESS_ERR};
479-
for(int i=0; i<3; i++)
480-
if(pipe_sources[process_io[i]] >= 0)
481-
if(pipe(pipes[process_io[i]]))
482-
return -1;
476+
for(int i=0; i<NUM_STREAM_SPECS; i++)
477+
if(has_pipes[i])
478+
if(pipe(pipes[i])) return -1;
483479

484480
// Fork child process
485481
stz_long pid = (stz_long)vfork();
@@ -493,19 +489,19 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
493489

494490
//Set up the pipes in the parent process.
495491
FILE* fin = NULL;
496-
if(pipe_sources[PROCESS_IN] >= 0) {
492+
if(has_pipes[PROCESS_IN]) {
497493
close(pipes[PROCESS_IN][0]);
498494
fin = fdopen(pipes[PROCESS_IN][1], "w");
499495
if(fin == NULL) goto return_error;
500496
}
501497
FILE* fout = NULL;
502-
if(pipe_sources[PROCESS_OUT] >= 0) {
498+
if(has_pipes[PROCESS_OUT]) {
503499
close(pipes[PROCESS_OUT][1]);
504500
fout = fdopen(pipes[PROCESS_OUT][0], "r");
505501
if(fout == NULL) goto return_error;
506502
}
507503
FILE* ferr = NULL;
508-
if(pipe_sources[PROCESS_ERR] >= 0) {
504+
if(has_pipes[PROCESS_ERR]) {
509505
close(pipes[PROCESS_ERR][1]);
510506
ferr = fdopen(pipes[PROCESS_ERR][0], "r");
511507
if(ferr == NULL) goto return_error;
@@ -521,59 +517,47 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
521517
//repeated by the autoreap handler.
522518
register_child_process(pid, fin, fout, ferr, &(process->status));
523519

520+
//Child process successfully launched and registered.
521+
goto return_success;
522+
524523
//Perform cleanup and return -1 to indicate error.
525524
return_error: {
526525
restore_signal_mask(&old_signal_mask);
527526
return -1;
528527
}
529528

530529
//Perform cleanup and return 0 to indicate success.
531-
return_success:{
530+
return_success: {
532531
restore_signal_mask(&old_signal_mask);
533532
return 0;
534533
}
535534
}
536535

537536
// Child: setup pipes, exec
538537
else {
539-
//Redirect stdout if necessary
540-
{
541-
int i = STANDARD_OUT;
542-
if(pipe_sources[i] >= 0 && pipe_sources[i] != STDOUT_FILENO)
543-
if(dup2(STDOUT_FILENO, pipe_sources[i]) < 0) exit(-1);
544-
}
545-
//Redirect stderr if necessary
546-
{
547-
int i = STANDARD_ERR;
548-
if(pipe_sources[i] >= 0 && pipe_sources[i] != STDERR_FILENO)
549-
if(dup2(STDERR_FILENO, pipe_sources[i]) < 0) exit(-1);
550-
}
551-
//Setup input pipe if used
552-
{
553-
int i = PROCESS_IN;
554-
if(pipe_sources[i] >= 0) {
555-
if(close(pipes[i][1]) < 0) exit(-1);
556-
if(dup2(pipes[i][0], pipe_sources[i]) < 0) exit(-1);
557-
if(close(pipes[i][0]) < 0) exit(-1);
558-
}
538+
//Connect process input pipe if necessary.
539+
if(has_pipes[PROCESS_IN]){
540+
if(close(pipes[PROCESS_IN][1]) < 0) exit(-1);
541+
if(dup2(pipes[PROCESS_IN][0], STDIN_FILENO) < 0) exit(-1);
542+
if(close(pipes[PROCESS_IN][0]) < 0) exit(-1);
559543
}
560-
//Setup output pipe if used
561-
{
562-
int i = PROCESS_OUT;
563-
if(pipe_sources[i] >= 0) {
564-
if(close(pipes[i][0]) < 0) exit(-1);
565-
if(dup2(pipes[i][1], pipe_sources[i]) < 0) exit(-1);
566-
if(close(pipes[i][1]) < 0) exit(-1);
567-
}
544+
//Connect process output pipe if necessary.
545+
if(has_pipes[PROCESS_OUT]){
546+
if(close(pipes[PROCESS_OUT][0]) < 0) exit(-1);
547+
if(output == PROCESS_OUT)
548+
if(dup2(pipes[PROCESS_OUT][1], STDOUT_FILENO) < 0) exit(-1);
549+
if(error == PROCESS_OUT)
550+
if(dup2(pipes[PROCESS_OUT][1], STDERR_FILENO) < 0) exit(-1);
551+
if(close(pipes[PROCESS_OUT][1]) < 0) exit(-1);
568552
}
569-
//Setup error pipe if used
570-
{
571-
int i = PROCESS_ERR;
572-
if(pipe_sources[i] >= 0) {
573-
if(close(pipes[i][0]) < 0) exit(-1);
574-
if(dup2(pipes[i][1], pipe_sources[i]) < 0) exit(-1);
575-
if(close(pipes[i][1]) < 0) exit(-1);
576-
}
553+
//Connect process error pipe if necessary.
554+
if(has_pipes[PROCESS_ERR]){
555+
if(close(pipes[PROCESS_ERR][0]) < 0) exit(-1);
556+
if(output == PROCESS_ERR)
557+
if(dup2(pipes[PROCESS_ERR][1], STDOUT_FILENO) < 0) exit(-1);
558+
if(error == PROCESS_ERR)
559+
if(dup2(pipes[PROCESS_ERR][1], STDERR_FILENO) < 0) exit(-1);
560+
if(close(pipes[PROCESS_ERR][1]) < 0) exit(-1);
577561
}
578562

579563
//Setup working directory

0 commit comments

Comments
 (0)