Skip to content

Commit 9915e41

Browse files
committed
updates to the process library
1 parent 4509418 commit 9915e41

2 files changed

Lines changed: 56 additions & 16 deletions

File tree

lang/libs/process/posix/posix.ch

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ using std::string;
66
using std::string_view;
77
using std::vector;
88

9+
// Redirect a file descriptor to /dev/null so un-captured output doesn't
10+
// leak to the parent's terminal.
11+
func redirect_to_devnull(fd : int) {
12+
var dn = open("/dev/null", O_WRONLY, 0);
13+
if(dn >= 0) {
14+
dup2(dn, fd);
15+
close(dn);
16+
} else {}
17+
}
18+
919
// POSIX impl returns bool: true=success, false=error (details in errno)
1020
public func posix_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool {
1121
unsafe var stdout_pipe : [2]int;
@@ -35,27 +45,30 @@ public func posix_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool
3545
} else {}
3646
if(cfg.capture_stdout) {
3747
close(stdout_pipe[0])
48+
dup2(stdout_pipe[1], 1)
3849
if(cfg.merge_stdout_stderr) {
3950
// Both stdout and stderr go to stdout_pipe[1]
40-
dup2(stdout_pipe[1], 1)
4151
dup2(stdout_pipe[1], 2)
42-
close(stdout_pipe[1])
43-
} else {
44-
dup2(stdout_pipe[1], 1)
45-
close(stdout_pipe[1])
4652
}
47-
} else {}
48-
if(cfg.capture_stderr && !cfg.merge_stdout_stderr) {
53+
close(stdout_pipe[1])
54+
} else if(cfg.merge_stdout_stderr) {
55+
// merge without capturing stdout: route both to stderr pipe
4956
close(stderr_pipe[0])
57+
dup2(stderr_pipe[1], 1)
5058
dup2(stderr_pipe[1], 2)
5159
close(stderr_pipe[1])
52-
} else if(cfg.merge_stdout_stderr && !cfg.capture_stdout) {
53-
// merge without capture_stdout: redirect both to stderr_pipe[1]
60+
} else {
61+
redirect_to_devnull(1)
62+
}
63+
if(cfg.merge_stdout_stderr) {
64+
// fd2 already handled above
65+
} else if(cfg.capture_stderr) {
5466
close(stderr_pipe[0])
55-
dup2(stderr_pipe[1], 1)
5667
dup2(stderr_pipe[1], 2)
5768
close(stderr_pipe[1])
58-
} else {}
69+
} else {
70+
redirect_to_devnull(2)
71+
}
5972
// stdin_data: create a temporary pipe in the child, write data, then dup2 to fd 0.
6073
// This is done in the child so the parent doesn't need a separate pipe.
6174
if(cfg.stdin_data.size() > 0) {
@@ -216,7 +229,9 @@ public func posix_spawn(cfg : *ProcessConfig, child : *mut ChildProcess) : bool
216229
dup2(stdout_pipe[1], 1)
217230
close(stdout_pipe[1])
218231
}
219-
} else {}
232+
} else {
233+
redirect_to_devnull(1)
234+
}
220235
if(cfg.capture_stderr && !cfg.merge_stdout_stderr) {
221236
close(stderr_pipe[0])
222237
dup2(stderr_pipe[1], 2)
@@ -227,6 +242,8 @@ public func posix_spawn(cfg : *ProcessConfig, child : *mut ChildProcess) : bool
227242
dup2(stderr_pipe[1], 1)
228243
dup2(stderr_pipe[1], 2)
229244
close(stderr_pipe[1])
245+
} else if(!cfg.merge_stdout_stderr && !cfg.capture_stderr) {
246+
redirect_to_devnull(2)
230247
} else {}
231248
// Child reads from stdin_pipe[0]; parent writes to stdin_pipe[1].
232249
close(stdin_pipe[1]); dup2(stdin_pipe[0], 0); close(stdin_pipe[0]);
@@ -366,6 +383,7 @@ func read_all_fd(fd : int, data : *mut vector<u8>) : bool {
366383

367384
const F_GETFL = 3
368385
const F_SETFL = 4
386+
const O_WRONLY = 1
369387
const O_NONBLOCK = 2048
370388
const EAGAIN = 11
371389
const X_OK = 1

lang/libs/process/win/win.ch

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ public func SetHandleInformation(hObject : HANDLE, dwMask : DWORD, dwFlags : DWO
4141
@extern
4242
func SetEnvironmentVariableA(name : *char, value : *char) : int;
4343

44+
@dllimport @extern @stdcall
45+
func CreateFileA(
46+
lpFileName : LPCSTR,
47+
dwDesiredAccess : DWORD,
48+
dwShareMode : DWORD,
49+
lpSecurityAttributes : *mut SECURITY_ATTRIBUTES,
50+
dwCreationDisposition : DWORD,
51+
dwFlagsAndAttributes : DWORD,
52+
hTemplateFile : HANDLE
53+
) : HANDLE;
54+
4455
// ---------------------------------------------------------------------------
4556
// Constants
4657
// ---------------------------------------------------------------------------
@@ -51,11 +62,22 @@ comptime const WAIT_OBJECT_0 : DWORD = 0 as DWORD;
5162
comptime const WAIT_TIMEOUT : DWORD = 258 as DWORD;
5263
comptime const INFINITE : DWORD = 0xFFFFFFFF as DWORD;
5364
comptime const HANDLE_FLAG_INHERIT : DWORD = 0x00000001 as DWORD;
65+
comptime const FILE_WRITE_DATA : DWORD = 0x00000002 as DWORD;
66+
comptime const OPEN_EXISTING : DWORD = 3 as DWORD;
67+
comptime const INVALID_HANDLE_VALUE : HANDLE = (0xFFFFFFFF as usize) as HANDLE;
5468

5569
// ---------------------------------------------------------------------------
5670
// Internal helpers
5771
// ---------------------------------------------------------------------------
5872

73+
/// Open NUL: (Windows /dev/null equivalent) so un-captured output doesn't
74+
/// leak to the parent's console.
75+
func win_open_nul() : HANDLE {
76+
var h = CreateFileA("NUL", FILE_WRITE_DATA, 0, null, OPEN_EXISTING, 0, null)
77+
if(h == INVALID_HANDLE_VALUE) { return GetStdHandle(STD_OUTPUT_HANDLE) }
78+
return h
79+
}
80+
5981
/// Read all data from a handle until EOF.
6082
func win_read_all(h : HANDLE, data : *mut vector<u8>) : bool {
6183
unsafe var buf : [4096]u8;
@@ -221,14 +243,14 @@ public func win_execute(cfg : *ProcessConfig, out : *mut ProcessResult) : bool {
221243
if(cfg.capture_stdout || cfg.merge_stdout_stderr) {
222244
si.hStdOutput = stdout_write
223245
} else {
224-
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
246+
si.hStdOutput = win_open_nul()
225247
}
226248
if(cfg.merge_stdout_stderr) {
227249
si.hStdError = stdout_write
228250
} else if(cfg.capture_stderr) {
229251
si.hStdError = stderr_write
230252
} else {
231-
si.hStdError = GetStdHandle(STD_ERROR_HANDLE)
253+
si.hStdError = win_open_nul()
232254
}
233255
if(has_stdin_data) {
234256
si.hStdInput = stdin_read
@@ -416,14 +438,14 @@ public func win_spawn(cfg : *ProcessConfig, child : *mut ChildProcess) : bool {
416438
if(cfg.capture_stdout || cfg.merge_stdout_stderr) {
417439
si.hStdOutput = stdout_write
418440
} else {
419-
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
441+
si.hStdOutput = win_open_nul()
420442
}
421443
if(cfg.merge_stdout_stderr) {
422444
si.hStdError = stdout_write
423445
} else if(cfg.capture_stderr) {
424446
si.hStdError = stderr_write
425447
} else {
426-
si.hStdError = GetStdHandle(STD_ERROR_HANDLE)
448+
si.hStdError = win_open_nul()
427449
}
428450
si.hStdInput = stdin_read
429451

0 commit comments

Comments
 (0)