mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Merge branch 'master' of https://github.com/odin-lang/Odin
This commit is contained in:
@@ -383,12 +383,23 @@ _make_dynamic_array_len_cap :: proc(array: ^Raw_Dynamic_Array, size_of_elem, ali
|
||||
return
|
||||
}
|
||||
|
||||
// `make_map` allocates and initializes a map. Like `new`, the first argument is a type, not a value.
|
||||
// `make_map` initializes a map with an allocator. Like `new`, the first argument is a type, not a value.
|
||||
// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
||||
//
|
||||
// Note: Prefer using the procedure group `make`.
|
||||
@(builtin, require_results)
|
||||
make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error {
|
||||
make_map :: proc($T: typeid/map[$K]$E, allocator := context.allocator) -> (m: T) {
|
||||
m.allocator = allocator
|
||||
return m
|
||||
}
|
||||
|
||||
// `make_map_cap` initializes a map with an allocator and allocates space using `capacity`.
|
||||
// Like `new`, the first argument is a type, not a value.
|
||||
// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
|
||||
//
|
||||
// Note: Prefer using the procedure group `make`.
|
||||
@(builtin, require_results)
|
||||
make_map_cap :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error {
|
||||
make_map_expr_error_loc(loc, capacity)
|
||||
context.allocator = allocator
|
||||
|
||||
@@ -425,6 +436,7 @@ make :: proc{
|
||||
make_dynamic_array_len,
|
||||
make_dynamic_array_len_cap,
|
||||
make_map,
|
||||
make_map_cap,
|
||||
make_multi_pointer,
|
||||
|
||||
make_soa_slice,
|
||||
|
||||
@@ -19,8 +19,8 @@ if "%VSCMD_ARG_TGT_ARCH%" neq "x64" (
|
||||
)
|
||||
)
|
||||
|
||||
for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime (
|
||||
set CURR_DATE_TIME=%%j
|
||||
for /f %%i in ('powershell get-date -format "{yyyyMMdd}"') do (
|
||||
set CURR_DATE_TIME=%%i
|
||||
)
|
||||
set curr_year=%CURR_DATE_TIME:~0,4%
|
||||
set curr_month=%CURR_DATE_TIME:~4,2%
|
||||
@@ -70,6 +70,7 @@ set rc_flags=-nologo ^
|
||||
-DV1=%V1% -DV2=%V2% -DV3=%V3% -DV4=%V4% ^
|
||||
-DVF=%odin_version_full% -DNIGHTLY=%nightly%
|
||||
|
||||
where /Q git.exe || goto skip_git_hash
|
||||
if not exist .git\ goto skip_git_hash
|
||||
for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m" --no-patch --no-notes HEAD') do (
|
||||
set odin_version_raw=dev-%%i
|
||||
|
||||
@@ -130,7 +130,7 @@ build_odin() {
|
||||
EXTRAFLAGS="-O3"
|
||||
;;
|
||||
release-native)
|
||||
if [ "$OS_ARCH" = "arm64" ]; then
|
||||
if [ "$OS_ARCH" = "arm64" ] || [ "$OS_ARCH" = "aarch64" ]; then
|
||||
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
|
||||
EXTRAFLAGS="-O3 -mcpu=native"
|
||||
else
|
||||
|
||||
@@ -62,8 +62,8 @@ TEMP_ALLOCATOR_GUARD_END :: proc(temp: runtime.Arena_Temp, loc := #caller_locati
|
||||
|
||||
@(deferred_out=TEMP_ALLOCATOR_GUARD_END)
|
||||
TEMP_ALLOCATOR_GUARD :: #force_inline proc(loc := #caller_location) -> (runtime.Arena_Temp, runtime.Source_Code_Location) {
|
||||
tmp := temp_allocator_temp_begin(loc)
|
||||
global_default_temp_allocator_index = (global_default_temp_allocator_index+1)%MAX_TEMP_ARENA_COUNT
|
||||
tmp := temp_allocator_temp_begin(loc)
|
||||
return tmp, loc
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@ _get_platform_error :: proc(errno: linux.Errno) -> Error {
|
||||
return .Invalid_File
|
||||
case .ENOMEM:
|
||||
return .Out_Of_Memory
|
||||
case .ENOSYS:
|
||||
return .Unsupported
|
||||
}
|
||||
|
||||
return Platform_Error(i32(errno))
|
||||
|
||||
@@ -26,6 +26,8 @@ _get_platform_error :: proc() -> Error {
|
||||
return .Invalid_File
|
||||
case .ENOMEM:
|
||||
return .Out_Of_Memory
|
||||
case .ENOSYS:
|
||||
return .Unsupported
|
||||
case:
|
||||
return Platform_Error(errno)
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (d
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
write_entire_file :: proc(name: string, data: []byte, perm: int, truncate := true) -> Error {
|
||||
write_entire_file :: proc(name: string, data: []byte, perm: int = 0o644, truncate := true) -> Error {
|
||||
flags := O_WRONLY|O_CREATE
|
||||
if truncate {
|
||||
flags |= O_TRUNC
|
||||
|
||||
@@ -40,7 +40,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
|
||||
|
||||
internal_mkdir_all :: proc(path: string, perm: int) -> Error {
|
||||
dir, file := filepath.split(path)
|
||||
if file != path {
|
||||
if file != path && dir != "/" {
|
||||
if len(dir) > 1 && dir[len(dir) - 1] == '/' {
|
||||
dir = dir[:len(dir) - 1]
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ _pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||
if r == nil || r.impl == nil {
|
||||
return false, nil
|
||||
}
|
||||
fd := posix.FD((^File_Impl)(r.impl).fd)
|
||||
fd := __fd(r)
|
||||
poll_fds := []posix.pollfd {
|
||||
posix.pollfd {
|
||||
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)
|
||||
if n != 1 {
|
||||
if n < 0 {
|
||||
return false, _get_platform_error()
|
||||
} else if n != 1 {
|
||||
return false, nil
|
||||
}
|
||||
pipe_events := poll_fds[0].revents
|
||||
if pipe_events >= {.IN} {
|
||||
@@ -68,4 +70,4 @@ _pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
|
||||
return false, .Broken_Pipe
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package os2
|
||||
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
import "core:time"
|
||||
|
||||
/*
|
||||
@@ -371,16 +371,18 @@ process_exec :: proc(
|
||||
loc := #caller_location,
|
||||
) -> (
|
||||
state: Process_State,
|
||||
stdout: []u8,
|
||||
stderr: []u8,
|
||||
stdout: []byte,
|
||||
stderr: []byte,
|
||||
err: Error,
|
||||
) {
|
||||
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)
|
||||
|
||||
stdout_r, stdout_w := pipe() or_return
|
||||
defer close(stdout_r)
|
||||
stderr_r, stderr_w := pipe() or_return
|
||||
defer close(stdout_w)
|
||||
defer close(stderr_r)
|
||||
|
||||
process: Process
|
||||
{
|
||||
// NOTE(flysand): Make sure the write-ends are closed, regardless
|
||||
@@ -392,45 +394,65 @@ process_exec :: proc(
|
||||
desc.stderr = stderr_w
|
||||
process = process_start(desc) or_return
|
||||
}
|
||||
stdout_builder := strings.builder_make(allocator) or_return
|
||||
stderr_builder := strings.builder_make(allocator) or_return
|
||||
read_data: for {
|
||||
buf: [1024]u8
|
||||
n: int
|
||||
has_data: bool
|
||||
hangup := false
|
||||
has_data, err = pipe_has_data(stdout_r)
|
||||
if has_data {
|
||||
n, err = read(stdout_r, buf[:])
|
||||
strings.write_bytes(&stdout_builder, buf[:n])
|
||||
}
|
||||
switch err {
|
||||
case nil: // nothing
|
||||
case .Broken_Pipe:
|
||||
hangup = true
|
||||
case:
|
||||
return
|
||||
}
|
||||
has_data, err = pipe_has_data(stderr_r)
|
||||
if has_data {
|
||||
n, err = read(stderr_r, buf[:])
|
||||
strings.write_bytes(&stderr_builder, buf[:n])
|
||||
}
|
||||
switch err {
|
||||
case nil: // nothing
|
||||
case .Broken_Pipe:
|
||||
hangup = true
|
||||
case:
|
||||
return
|
||||
}
|
||||
if hangup {
|
||||
break read_data
|
||||
|
||||
{
|
||||
stdout_b: [dynamic]byte
|
||||
stdout_b.allocator = allocator
|
||||
defer stdout = stdout_b[:]
|
||||
|
||||
stderr_b: [dynamic]byte
|
||||
stderr_b.allocator = allocator
|
||||
defer stderr = stderr_b[:]
|
||||
|
||||
buf: [1024]u8 = ---
|
||||
|
||||
stdout_done, stderr_done, has_data: bool
|
||||
for err == nil && (!stdout_done || !stderr_done) {
|
||||
n := 0
|
||||
|
||||
if !stdout_done {
|
||||
has_data, err = pipe_has_data(stdout_r)
|
||||
if has_data {
|
||||
n, err = read(stdout_r, buf[:])
|
||||
}
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
_, err = append(&stdout_b, ..buf[:n])
|
||||
case .EOF, .Broken_Pipe:
|
||||
stdout_done = true
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && !stderr_done {
|
||||
n = 0
|
||||
has_data, err = pipe_has_data(stderr_r)
|
||||
if has_data {
|
||||
n, err = read(stderr_r, buf[:])
|
||||
}
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
_, err = append(&stderr_b, ..buf[:n])
|
||||
case .EOF, .Broken_Pipe:
|
||||
stderr_done = true
|
||||
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
|
||||
|
||||
if err != nil {
|
||||
state, _ = process_wait(process, timeout=0)
|
||||
if !state.exited {
|
||||
_ = process_kill(process)
|
||||
state, _ = process_wait(process)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
state, err = process_wait(process)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -523,7 +523,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
write_errno_to_parent_and_abort :: proc(parent_fd: linux.Fd, errno: linux.Errno) -> ! {
|
||||
error_byte: [1]u8 = { u8(errno) }
|
||||
linux.write(parent_fd, error_byte[:])
|
||||
intrinsics.trap()
|
||||
linux.exit(126)
|
||||
}
|
||||
|
||||
stdin_fd: linux.Fd
|
||||
|
||||
@@ -163,7 +163,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
#assert(len(posix.Errno) < max(u8))
|
||||
errno := u8(posix.errno())
|
||||
posix.write(parent_fd, &errno, 1)
|
||||
runtime.trap()
|
||||
posix.exit(126)
|
||||
}
|
||||
|
||||
null := posix.open("/dev/null", {.RDWR})
|
||||
@@ -223,7 +223,6 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
process.pid = int(pid)
|
||||
process, _ = _process_open(int(pid), {})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ _process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error)
|
||||
}
|
||||
|
||||
_process_open :: proc(pid: int, flags: Process_Open_Flags) -> (process: Process, err: Error) {
|
||||
process.pid = pid
|
||||
err = .Unsupported
|
||||
return
|
||||
}
|
||||
|
||||
@@ -650,26 +650,30 @@ _build_command_line :: proc(command: []string, allocator: runtime.Allocator) ->
|
||||
strings.write_byte(&builder, ' ')
|
||||
}
|
||||
j := 0
|
||||
strings.write_byte(&builder, '"')
|
||||
for j < len(arg) {
|
||||
backslashes := 0
|
||||
for j < len(arg) && arg[j] == '\\' {
|
||||
backslashes += 1
|
||||
if strings.contains_any(arg, "()[]{}^=;!'+,`~\" ") {
|
||||
strings.write_byte(&builder, '"')
|
||||
for j < len(arg) {
|
||||
backslashes := 0
|
||||
for j < len(arg) && arg[j] == '\\' {
|
||||
backslashes += 1
|
||||
j += 1
|
||||
}
|
||||
if j == len(arg) {
|
||||
_write_byte_n_times(&builder, '\\', 2*backslashes)
|
||||
break
|
||||
} else if arg[j] == '"' {
|
||||
_write_byte_n_times(&builder, '\\', 2*backslashes+1)
|
||||
strings.write_byte(&builder, arg[j])
|
||||
} else {
|
||||
_write_byte_n_times(&builder, '\\', backslashes)
|
||||
strings.write_byte(&builder, arg[j])
|
||||
}
|
||||
j += 1
|
||||
}
|
||||
if j == len(arg) {
|
||||
_write_byte_n_times(&builder, '\\', 2*backslashes)
|
||||
break
|
||||
} else if arg[j] == '"' {
|
||||
_write_byte_n_times(&builder, '\\', 2*backslashes+1)
|
||||
strings.write_byte(&builder, '"')
|
||||
} else {
|
||||
_write_byte_n_times(&builder, '\\', backslashes)
|
||||
strings.write_byte(&builder, arg[j])
|
||||
}
|
||||
j += 1
|
||||
strings.write_byte(&builder, '"')
|
||||
} else {
|
||||
strings.write_string(&builder, arg)
|
||||
}
|
||||
strings.write_byte(&builder, '"')
|
||||
}
|
||||
return strings.to_string(builder)
|
||||
}
|
||||
|
||||
@@ -124,11 +124,11 @@ WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
|
||||
idtype_t :: enum c.int {
|
||||
// Wait for any children and `id` is ignored.
|
||||
P_ALL,
|
||||
P_ALL = _P_ALL,
|
||||
// Wait for any child wiith a process group ID equal to `id`.
|
||||
P_PID,
|
||||
P_PID = _P_PID,
|
||||
// Wait for any child with a process group ID equal to `id`.
|
||||
P_PGID,
|
||||
P_PGID = _P_PGID,
|
||||
}
|
||||
|
||||
Wait_Flag_Bits :: enum c.int {
|
||||
@@ -166,6 +166,10 @@ when ODIN_OS == .Darwin {
|
||||
WNOWAIT :: 0x00000020
|
||||
WSTOPPED :: 0x00000008
|
||||
|
||||
_P_ALL :: 0
|
||||
_P_PID :: 1
|
||||
_P_PGID :: 2
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
@@ -221,6 +225,10 @@ when ODIN_OS == .Darwin {
|
||||
WNOWAIT :: 8
|
||||
WSTOPPED :: 2
|
||||
|
||||
_P_ALL :: 7
|
||||
_P_PID :: 0
|
||||
_P_PGID :: 2
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
@@ -275,6 +283,10 @@ when ODIN_OS == .Darwin {
|
||||
WNOWAIT :: 0x00010000
|
||||
WSTOPPED :: 0x00000002
|
||||
|
||||
_P_ALL :: 0
|
||||
_P_PID :: 1
|
||||
_P_PGID :: 2
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
@@ -330,6 +342,10 @@ when ODIN_OS == .Darwin {
|
||||
WNOWAIT :: 0x00010000
|
||||
WSTOPPED :: 0x00000002
|
||||
|
||||
_P_ALL :: 0
|
||||
_P_PID :: 2
|
||||
_P_PGID :: 1
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
|
||||
@@ -253,8 +253,6 @@ FILE_GENERIC_WRITE: DWORD : STANDARD_RIGHTS_WRITE |
|
||||
FILE_APPEND_DATA |
|
||||
SYNCHRONIZE
|
||||
|
||||
FILE_FLAG_OPEN_REPARSE_POINT: DWORD : 0x00200000
|
||||
FILE_FLAG_BACKUP_SEMANTICS: DWORD : 0x02000000
|
||||
SECURITY_SQOS_PRESENT: DWORD : 0x00100000
|
||||
|
||||
FIONBIO: c_ulong : 0x8004667e
|
||||
@@ -2222,11 +2220,22 @@ WAIT_OBJECT_0: DWORD : 0x00000000
|
||||
WAIT_TIMEOUT: DWORD : 258
|
||||
WAIT_FAILED: DWORD : 0xFFFFFFFF
|
||||
|
||||
FILE_FLAG_WRITE_THROUGH: DWORD : 0x80000000
|
||||
FILE_FLAG_OVERLAPPED: DWORD : 0x40000000
|
||||
FILE_FLAG_NO_BUFFERING: DWORD : 0x20000000
|
||||
FILE_FLAG_RANDOM_ACCESS: DWORD : 0x10000000
|
||||
FILE_FLAG_SEQUENTIAL_SCAN: DWORD : 0x08000000
|
||||
FILE_FLAG_DELETE_ON_CLOSE: DWORD : 0x04000000
|
||||
FILE_FLAG_BACKUP_SEMANTICS: DWORD : 0x02000000
|
||||
FILE_FLAG_POSIX_SEMANTICS: DWORD : 0x01000000
|
||||
FILE_FLAG_SESSION_AWARE: DWORD : 0x00800000
|
||||
FILE_FLAG_OPEN_REPARSE_POINT: DWORD : 0x00200000
|
||||
FILE_FLAG_OPEN_NO_RECALL: DWORD : 0x00100000
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000
|
||||
|
||||
PIPE_ACCESS_INBOUND: DWORD : 0x00000001
|
||||
PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002
|
||||
PIPE_ACCESS_DUPLEX: DWORD : 0x00000003
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000
|
||||
FILE_FLAG_OVERLAPPED: DWORD : 0x40000000
|
||||
PIPE_WAIT: DWORD : 0x00000000
|
||||
PIPE_TYPE_BYTE: DWORD : 0x00000000
|
||||
PIPE_TYPE_MESSAGE: DWORD : 0x00000004
|
||||
|
||||
@@ -8795,11 +8795,6 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
|
||||
return kind;
|
||||
}
|
||||
|
||||
if (x.type == nullptr || x.type == t_invalid ||
|
||||
y.type == nullptr || y.type == t_invalid) {
|
||||
return kind;
|
||||
}
|
||||
|
||||
bool use_type_hint = type_hint != nullptr && (is_operand_nil(x) || is_operand_nil(y));
|
||||
|
||||
convert_to_typed(c, &x, use_type_hint ? type_hint : y.type);
|
||||
|
||||
@@ -1225,10 +1225,10 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV
|
||||
lbValue d3 = lb_emit_struct_ep(p, res.addr, 3);
|
||||
|
||||
if (immediate_type != ft) {
|
||||
d0 = lb_emit_conv(p, d0, ft);
|
||||
d1 = lb_emit_conv(p, d1, ft);
|
||||
d2 = lb_emit_conv(p, d2, ft);
|
||||
d3 = lb_emit_conv(p, d3, ft);
|
||||
z0 = lb_emit_conv(p, z0, ft);
|
||||
z1 = lb_emit_conv(p, z1, ft);
|
||||
z2 = lb_emit_conv(p, z2, ft);
|
||||
z3 = lb_emit_conv(p, z3, ft);
|
||||
}
|
||||
|
||||
lb_emit_store(p, d0, z0);
|
||||
|
||||
@@ -33,6 +33,7 @@ download_assets :: proc() {
|
||||
@(require) import "net"
|
||||
@(require) import "odin"
|
||||
@(require) import "os"
|
||||
@(require) import "os/os2"
|
||||
@(require) import "path/filepath"
|
||||
@(require) import "reflect"
|
||||
@(require) import "runtime"
|
||||
|
||||
25
tests/core/os/os2/process.odin
Normal file
25
tests/core/os/os2/process.odin
Normal file
@@ -0,0 +1,25 @@
|
||||
package tests_core_os_os2
|
||||
|
||||
import os "core:os/os2"
|
||||
import "core:log"
|
||||
import "core:testing"
|
||||
|
||||
@(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)
|
||||
|
||||
if err == .Unsupported {
|
||||
log.warn("process_exec unsupported")
|
||||
return
|
||||
}
|
||||
|
||||
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")
|
||||
testing.expect_value(t, string(stderr), "")
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
#+build darwin, freebsd, openbsd, netbsd
|
||||
package tests_core_posix
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
import "core:log"
|
||||
import "core:path/filepath"
|
||||
import "core:strings"
|
||||
@@ -217,52 +215,6 @@ test_termios :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._FFDLY), posix.FFDLY)
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_signal :: proc(t: ^testing.T) {
|
||||
@static tt: ^testing.T
|
||||
tt = t
|
||||
|
||||
@static ctx: runtime.Context
|
||||
ctx = context
|
||||
|
||||
act: posix.sigaction_t
|
||||
act.sa_flags = {.SIGINFO, .RESETHAND}
|
||||
act.sa_sigaction = handler
|
||||
testing.expect_value(t, posix.sigaction(.SIGCHLD, &act, nil), posix.result.OK)
|
||||
|
||||
handler :: proc "c" (sig: posix.Signal, info: ^posix.siginfo_t, address: rawptr) {
|
||||
context = ctx
|
||||
testing.expect_value(tt, sig, posix.Signal.SIGCHLD)
|
||||
testing.expect_value(tt, info.si_signo, posix.Signal.SIGCHLD)
|
||||
testing.expect_value(tt, info.si_status, 69)
|
||||
testing.expect_value(tt, info.si_code.chld, posix.CLD_Code.EXITED)
|
||||
}
|
||||
|
||||
switch pid := posix.fork(); pid {
|
||||
case -1:
|
||||
log.errorf("fork() failure: %v", posix.strerror())
|
||||
case 0:
|
||||
posix.exit(69)
|
||||
case:
|
||||
for {
|
||||
status: i32
|
||||
res := posix.waitpid(pid, &status, {})
|
||||
if res == -1 {
|
||||
if !testing.expect_value(t, posix.errno(), posix.Errno.EINTR) {
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if posix.WIFEXITED(status) || posix.WIFSIGNALED(status) {
|
||||
testing.expect(t, posix.WIFEXITED(status))
|
||||
testing.expect(t, posix.WEXITSTATUS(status) == 69)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_pthreads :: proc(t: ^testing.T) {
|
||||
testing.set_fail_timeout(t, time.Second)
|
||||
|
||||
Reference in New Issue
Block a user