mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
fix os2.process_exec on non-windows and add a smoke test
This commit is contained in:
@@ -49,7 +49,7 @@ _pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
|||||||
if r == nil || r.impl == nil {
|
if r == nil || r.impl == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
fd := posix.FD((^File_Impl)(r.impl).fd)
|
fd := __fd(r)
|
||||||
poll_fds := []posix.pollfd {
|
poll_fds := []posix.pollfd {
|
||||||
posix.pollfd {
|
posix.pollfd {
|
||||||
fd = fd,
|
fd = fd,
|
||||||
@@ -57,8 +57,10 @@ _pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
n := posix.poll(raw_data(poll_fds), u32(len(poll_fds)), 0)
|
n := posix.poll(raw_data(poll_fds), u32(len(poll_fds)), 0)
|
||||||
if n != 1 {
|
if n < 0 {
|
||||||
return false, _get_platform_error()
|
return false, _get_platform_error()
|
||||||
|
} else if n != 1 {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
pipe_events := poll_fds[0].revents
|
pipe_events := poll_fds[0].revents
|
||||||
if pipe_events >= {.IN} {
|
if pipe_events >= {.IN} {
|
||||||
|
|||||||
+44
-32
@@ -371,16 +371,18 @@ process_exec :: proc(
|
|||||||
loc := #caller_location,
|
loc := #caller_location,
|
||||||
) -> (
|
) -> (
|
||||||
state: Process_State,
|
state: Process_State,
|
||||||
stdout: []u8,
|
stdout: []byte,
|
||||||
stderr: []u8,
|
stderr: []byte,
|
||||||
err: Error,
|
err: Error,
|
||||||
) {
|
) {
|
||||||
assert(desc.stdout == nil, "Cannot redirect stdout when it's being captured", loc)
|
assert(desc.stdout == nil, "Cannot redirect stdout when it's being captured", loc)
|
||||||
assert(desc.stderr == nil, "Cannot redirect stderr when it's being captured", loc)
|
assert(desc.stderr == nil, "Cannot redirect stderr when it's being captured", loc)
|
||||||
|
|
||||||
stdout_r, stdout_w := pipe() or_return
|
stdout_r, stdout_w := pipe() or_return
|
||||||
defer close(stdout_r)
|
defer close(stdout_r)
|
||||||
stderr_r, stderr_w := pipe() or_return
|
stderr_r, stderr_w := pipe() or_return
|
||||||
defer close(stdout_w)
|
defer close(stdout_w)
|
||||||
|
|
||||||
process: Process
|
process: Process
|
||||||
{
|
{
|
||||||
// NOTE(flysand): Make sure the write-ends are closed, regardless
|
// NOTE(flysand): Make sure the write-ends are closed, regardless
|
||||||
@@ -392,44 +394,54 @@ process_exec :: proc(
|
|||||||
desc.stderr = stderr_w
|
desc.stderr = stderr_w
|
||||||
process = process_start(desc) or_return
|
process = process_start(desc) or_return
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout_builder := strings.builder_make(allocator) or_return
|
stdout_builder := strings.builder_make(allocator) or_return
|
||||||
stderr_builder := strings.builder_make(allocator) or_return
|
stderr_builder := strings.builder_make(allocator) or_return
|
||||||
read_data: for {
|
|
||||||
buf: [1024]u8
|
has_stdout, has_stderr: bool
|
||||||
|
read_data: for !has_stdout || !has_stderr {
|
||||||
|
buf: [1024]u8 = ---
|
||||||
n: int
|
n: int
|
||||||
has_data: bool
|
has_data: bool
|
||||||
hangup := false
|
|
||||||
has_data, err = pipe_has_data(stdout_r)
|
if !has_stdout {
|
||||||
if has_data {
|
has_data, err = pipe_has_data(stdout_r)
|
||||||
n, err = read(stdout_r, buf[:])
|
if has_data {
|
||||||
strings.write_bytes(&stdout_builder, buf[:n])
|
n, err = read(stdout_r, buf[:])
|
||||||
|
if strings.write_bytes(&stdout_builder, buf[:n]) != n {
|
||||||
|
err = .Out_Of_Memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch err {
|
||||||
|
case nil: // nothing
|
||||||
|
case .EOF, .Broken_Pipe:
|
||||||
|
stdout = stdout_builder.buf[:]
|
||||||
|
has_stdout = true
|
||||||
|
case:
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch err {
|
|
||||||
case nil: // nothing
|
if !has_stderr {
|
||||||
case .Broken_Pipe:
|
has_data, err = pipe_has_data(stderr_r)
|
||||||
hangup = true
|
if has_data {
|
||||||
case:
|
n, err = read(stderr_r, buf[:])
|
||||||
return
|
if strings.write_bytes(&stderr_builder, buf[:n]) != n {
|
||||||
}
|
err = .Out_Of_Memory
|
||||||
has_data, err = pipe_has_data(stderr_r)
|
}
|
||||||
if has_data {
|
}
|
||||||
n, err = read(stderr_r, buf[:])
|
switch err {
|
||||||
strings.write_bytes(&stderr_builder, buf[:n])
|
case nil: // nothing
|
||||||
}
|
case .EOF, .Broken_Pipe:
|
||||||
switch err {
|
stderr = stderr_builder.buf[:]
|
||||||
case nil: // nothing
|
has_stderr = true
|
||||||
case .Broken_Pipe:
|
case:
|
||||||
hangup = true
|
return
|
||||||
case:
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
if hangup {
|
|
||||||
break read_data
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = nil
|
err = nil
|
||||||
stdout = transmute([]u8) strings.to_string(stdout_builder)
|
|
||||||
stderr = transmute([]u8) strings.to_string(stderr_builder)
|
|
||||||
state = process_wait(process) or_return
|
state = process_wait(process) or_return
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ download_assets :: proc() {
|
|||||||
@(require) import "net"
|
@(require) import "net"
|
||||||
@(require) import "odin"
|
@(require) import "odin"
|
||||||
@(require) import "os"
|
@(require) import "os"
|
||||||
|
@(require) import "os/os2"
|
||||||
@(require) import "path/filepath"
|
@(require) import "path/filepath"
|
||||||
@(require) import "reflect"
|
@(require) import "reflect"
|
||||||
@(require) import "runtime"
|
@(require) import "runtime"
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package tests_core_os_os2
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
|
||||||
|
import "core:log"
|
||||||
|
import os "core:os/os2"
|
||||||
|
import "core:testing"
|
||||||
|
|
||||||
|
_ :: log
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
test_process_exec :: proc(t: ^testing.T) {
|
||||||
|
state, stdout, stderr, err := os.process_exec({
|
||||||
|
command = {"echo", "hellope"},
|
||||||
|
}, context.allocator)
|
||||||
|
defer delete(stdout)
|
||||||
|
defer delete(stderr)
|
||||||
|
|
||||||
|
when (ODIN_OS not_in runtime.Odin_OS_Types{.Linux, .Darwin, .Windows}) {
|
||||||
|
testing.expect_value(t, err, os.General_Error.Unsupported)
|
||||||
|
_ = state
|
||||||
|
} else {
|
||||||
|
testing.expect_value(t, state.exited, true)
|
||||||
|
testing.expect_value(t, state.success, true)
|
||||||
|
testing.expect_value(t, err, nil)
|
||||||
|
testing.expect_value(t, string(stdout), "hellope\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user