@@ -585,6 +585,42 @@ static void *Task_Ready;
585
585
//SetEvent(Task_Ready);
586
586
}
587
587
588
+ //Helper function for OS_Create_Process:
589
+ //see: https://stackoverflow.com/questions/41976446/pipe2-vs-pipe-fcntl-why-different
590
+ static inline REBOOL Open_Pipe_Fails (int pipefd [2 ]) {
591
+ #ifdef USE_OLD_PIPE
592
+ //
593
+ // NOTE: pipe() is POSIX, but pipe2() is Linux-specific. With pipe() it
594
+ // takes an additional call to fcntl() to request non-blocking behavior,
595
+ // so it's a small amount more work. However, there are other flags which
596
+ // if aren't passed atomically at the moment of opening allow for a race
597
+ // condition in threading if split, e.g. FD_CLOEXEC.
598
+ //
599
+ // (If you don't have FD_CLOEXEC set on the file descriptor, then all
600
+ // instances of CALL will act as a /WAIT.)
601
+ //
602
+ // At time of writing, this is mostly academic...but the code needed to be
603
+ // patched to work with pipe() since some older libcs do not have pipe2().
604
+ // So the ability to target both are kept around, saving the pipe2() call
605
+ // for later Linuxes known to have it (and O_CLOEXEC).
606
+ //
607
+ if (pipe (pipefd ) < 0 )
608
+ return TRUE;
609
+ int direction ; // READ=0, WRITE=1
610
+ for (direction = 0 ; direction < 2 ; ++ direction ) {
611
+ int oldflags = fcntl (pipefd [direction ], F_GETFD );
612
+ if (oldflags < 0 )
613
+ return TRUE;
614
+ if (fcntl (pipefd [direction ], F_SETFD , oldflags | FD_CLOEXEC ) < 0 )
615
+ return TRUE;
616
+ }
617
+ #else
618
+ if (pipe2 (pipefd , O_CLOEXEC ))
619
+ return TRUE;
620
+ #endif
621
+ return FALSE;
622
+ }
623
+
588
624
589
625
/***********************************************************************
590
626
**
@@ -641,26 +677,23 @@ static void *Task_Ready;
641
677
if (flags & FLAG_SHELL ) flag_shell = TRUE;
642
678
if (flags & FLAG_INFO ) flag_info = TRUE;
643
679
644
- if (input_type == STRING_TYPE
645
- || input_type == BINARY_TYPE ) {
646
- if (pipe2 (stdin_pipe , O_CLOEXEC | O_NONBLOCK ) < 0 ) {
680
+ if (input_type == STRING_TYPE || input_type == BINARY_TYPE ) {
681
+ if (Open_Pipe_Fails (stdin_pipe )) {
647
682
goto stdin_pipe_err ;
648
683
}
649
684
}
650
- if (output_type == STRING_TYPE
651
- || output_type == BINARY_TYPE ) {
652
- if (pipe2 (stdout_pipe , O_CLOEXEC | O_NONBLOCK ) < 0 ) {
685
+ if (output_type == STRING_TYPE || output_type == BINARY_TYPE ) {
686
+ if (Open_Pipe_Fails (stdout_pipe )) {
653
687
goto stdout_pipe_err ;
654
688
}
655
689
}
656
- if (err_type == STRING_TYPE
657
- || err_type == BINARY_TYPE ) {
658
- if (pipe2 (stderr_pipe , O_CLOEXEC | O_NONBLOCK ) < 0 ) {
690
+ if (err_type == STRING_TYPE || err_type == BINARY_TYPE ) {
691
+ if (Open_Pipe_Fails (stderr_pipe )) {
659
692
goto stderr_pipe_err ;
660
693
}
661
694
}
662
695
663
- if (pipe2 (info_pipe , O_CLOEXEC | O_NONBLOCK ) < 0 ) {
696
+ if (Open_Pipe_Fails (info_pipe ) ) {
664
697
goto info_pipe_err ;
665
698
}
666
699
@@ -760,7 +793,9 @@ static void *Task_Ready;
760
793
sh = getenv ("SHELL" );
761
794
if (sh == NULL ) {
762
795
int err = 2 ; /* shell does not exist */
763
- write (info_pipe [W ], & err , sizeof (err ));
796
+ if (write (info_pipe [W ], & err , sizeof (err )) == -1 ) {
797
+ //nothing there... just to avoid "unused-result" compiler warning
798
+ }
764
799
exit (EXIT_FAILURE );
765
800
}
766
801
argv_new = OS_Make ((argc + 3 ) * sizeof (char * ));
@@ -773,7 +808,9 @@ static void *Task_Ready;
773
808
execvp (argv [0 ], argv );
774
809
}
775
810
child_error :
776
- write (info_pipe [W ], & errno , sizeof (errno ));
811
+ if (write (info_pipe [W ], & errno , sizeof (errno )) == -1 ) {
812
+ //nothing there... just to avoid "unused-result" compiler warning
813
+ }
777
814
exit (EXIT_FAILURE ); /* get here only when exec fails */
778
815
} else if (fpid > 0 ) {
779
816
/* parent */
0 commit comments