Skip to content

Commit f642f26

Browse files
committed
FEAT: posibility to use pipe() where pipe2() is not available
1 parent d78caf6 commit f642f26

File tree

2 files changed

+60
-22
lines changed

2 files changed

+60
-22
lines changed

src/os/posix/host-lib.c

+49-12
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,42 @@ static void *Task_Ready;
585585
//SetEvent(Task_Ready);
586586
}
587587

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+
588624

589625
/***********************************************************************
590626
**
@@ -641,26 +677,23 @@ static void *Task_Ready;
641677
if (flags & FLAG_SHELL) flag_shell = TRUE;
642678
if (flags & FLAG_INFO) flag_info = TRUE;
643679

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)) {
647682
goto stdin_pipe_err;
648683
}
649684
}
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)) {
653687
goto stdout_pipe_err;
654688
}
655689
}
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)) {
659692
goto stderr_pipe_err;
660693
}
661694
}
662695

663-
if (pipe2(info_pipe, O_CLOEXEC | O_NONBLOCK) < 0) {
696+
if (Open_Pipe_Fails(info_pipe)) {
664697
goto info_pipe_err;
665698
}
666699

@@ -760,7 +793,9 @@ static void *Task_Ready;
760793
sh = getenv("SHELL");
761794
if (sh == NULL) {
762795
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+
}
764799
exit(EXIT_FAILURE);
765800
}
766801
argv_new = OS_Make((argc + 3) * sizeof(char*));
@@ -773,7 +808,9 @@ static void *Task_Ready;
773808
execvp(argv[0], argv);
774809
}
775810
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+
}
777814
exit(EXIT_FAILURE); /* get here only when exec fails */
778815
} else if (fpid > 0) {
779816
/* parent */

src/tools/systems.r

+11-10
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ REBOL [
2121
systems: [
2222
[plat os-name os-base build-flags]
2323
[0.1.03 "amiga" posix [BEN HID NPS +SC CMT COP -SP -LM]]
24-
[0.2.04 "osx" posix [BEN +OS NCM -LM]] ; OSX/PPC; no shared lib possible
25-
[0.2.05 "osxi" posix [LEN ARC +O1 NPS PIC NCM HID STX -LM]]
26-
[0.2.40 "osx_x64" posix [LEN +O1 NPS PIC NCM HID STX -LM]]
24+
[0.2.04 "osx" posix [BEN +OS NCM -LM UOP]] ; OSX/PPC; no shared lib possible
25+
[0.2.05 "osxi" posix [LEN ARC +O1 NPS PIC NCM HID STX -LM UOP]]
26+
[0.2.40 "osx_x64" posix [LEN +O1 NPS PIC NCM HID STX -LM UOP]]
2727
[0.3.01 "win32" win32 [LEN +O2 UNI M32 W32 CON S4M EXE DIR -LM]]
2828
[0.3.40 "win32_x64" win32 [LEN +O2 UNI M64 P64 W32 CON S4M EXE DIR -LM]]
2929
[0.4.02 "linux" posix [LEN +O2 PIC LDL ST1 -LM]] ; libc 2.3
30-
[0.4.03 "linux" posix [LEN +O2 PIC HID LDL ST1 -LM]] ; libc 2.5
31-
[0.4.04 "linux" posix [LEN +O2 PIC HID LDL ST1 M32 -LM]] ; libc 2.11
32-
[0.4.10 "linux_ppc" posix [BEN +O1 PIC HID LDL ST1 -LM]]
33-
[0.4.20 "linux_arm" posix [LEN +O2 PIC HID LDL ST1 -LM]]
34-
[0.4.21 "linux_arm" posix [LEN +O2 PIE HID LDL ST1 -LM]] ; bionic (Android)
35-
[0.4.30 "linux_mips" posix [LEN +O2 PIC HID LDL ST1 -LM]]
36-
[0.4.40 "linux_x64" posix [LEN +O2 PIC HID LDL ST1 -LM]]
30+
[0.4.03 "linux" posix [LEN +O2 PIC LDL ST1 -LM HID]] ; libc 2.5
31+
[0.4.04 "linux" posix [LEN +O2 PIC LDL ST1 -LM HID M32]] ; libc 2.11
32+
[0.4.10 "linux_ppc" posix [BEN +O1 PIC LDL ST1 -LM HID]]
33+
[0.4.20 "linux_arm" posix [LEN +O2 PIC LDL ST1 -LM HID]]
34+
[0.4.21 "linux_arm" posix [LEN +O2 PIE LDL ST1 -LM HID]] ; bionic (Android)
35+
[0.4.30 "linux_mips" posix [LEN +O2 PIC LDL ST1 -LM HID]]
36+
[0.4.40 "linux_x64" posix [LEN +O2 PIC LDL ST1 -LM HID]]
3737
[0.5.75 "haiku" posix [LEN +O2 ST1 NWK]]
3838
[0.7.02 "freebsd" posix [LEN +O1 ST1 -LM]]
3939
[0.7.40 "freebsd_x64" posix [LEN +O1 ST1 -LM]]
@@ -62,6 +62,7 @@ compile-flags: [
6262
M64: "-m64" ; use 64-bit memory model
6363
LEN: "-DENDIAN_LITTLE" ; uses little endian byte order
6464
BEN: "-DENDIAN_BIG" ; uses big endian byte order
65+
UOP: "-DUSE_OLD_PIPE" ; use pipe() instead of pipe2(), which may not be supported
6566
]
6667

6768
linker-flags: [

0 commit comments

Comments
 (0)