aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jkercher43@gmail.com>2024-06-28 09:45:22 -0400
committerjason <jkercher43@gmail.com>2024-06-28 09:45:22 -0400
commit6a894195cbcf2caab2d84d75cc33f933e2390774 (patch)
tree7023ac02835048662c7e680a916633f61162d27d
parentdc954307d71b1602e50310d578070cb1547780e7 (diff)
revert os2/process
-rw-r--r--core/os/os2/process.odin88
-rw-r--r--core/os/os2/process_linux.odin428
-rw-r--r--core/os/os2/process_windows.odin67
3 files changed, 35 insertions, 548 deletions
diff --git a/core/os/os2/process.odin b/core/os/os2/process.odin
index 099d1c19e..862434b7b 100644
--- a/core/os/os2/process.odin
+++ b/core/os/os2/process.odin
@@ -2,42 +2,36 @@ package os2
import "core:sync"
import "core:time"
-import "core:c"
+import "base:runtime"
-args: []string = _alloc_command_line_arguments()
+args: []string
exit :: proc "contextless" (code: int) -> ! {
- _exit(code)
+ runtime.trap()
}
-@(require_results)
get_uid :: proc() -> int {
- return _get_uid()
+ return -1
}
-@(require_results)
get_euid :: proc() -> int {
- return _get_euid()
+ return -1
}
-@(require_results)
get_gid :: proc() -> int {
- return _get_gid()
+ return -1
}
-@(require_results)
get_egid :: proc() -> int {
- return _get_euid()
+ return -1
}
-@(require_results)
get_pid :: proc() -> int {
- return _get_pid()
+ return -1
}
-@(require_results)
get_ppid :: proc() -> int {
- return _get_ppid()
+ return -1
}
@@ -52,12 +46,16 @@ Process :: struct {
Process_Attributes :: struct {
dir: string,
env: []string,
- stdin: ^File,
- stdout: ^File,
- stderr: ^File,
+ files: []^File,
sys: ^Process_Attributes_OS_Specific,
}
+Process_Attributes_OS_Specific :: struct{}
+
+Process_Error :: enum {
+ None,
+}
+
Process_State :: struct {
pid: int,
exit_code: int,
@@ -68,53 +66,37 @@ Process_State :: struct {
sys: rawptr,
}
-Signal :: enum {
- Abort,
- Floating_Point_Exception,
- Illegal_Instruction,
- Interrupt,
- Segmentation_Fault,
- Termination,
-}
+Signal :: #type proc()
-Signal_Handler_Proc :: #type proc "c" (c.int)
-Signal_Handler_Special :: enum {
- Default,
- Ignore,
-}
+Kill: Signal = nil
+Interrupt: Signal = nil
-Signal_Handler :: union {
- Signal_Handler_Proc,
- Signal_Handler_Special,
-}
-@(require_results)
-process_find :: proc(pid: int) -> (Process, Error) {
- return _process_find(pid)
+find_process :: proc(pid: int) -> (^Process, Process_Error) {
+ return nil, .None
}
-@(require_results)
-process_get_state :: proc(p: Process) -> (Process_State, Error) {
- return _process_get_state(p)
-}
-@(require_results)
-process_start :: proc(name: string, argv: []string, attr: ^Process_Attributes = nil) -> (Process, Error) {
- return _process_start(name, argv, attr)
+process_start :: proc(name: string, argv: []string, attr: ^Process_Attributes) -> (^Process, Process_Error) {
+ return nil, .None
}
-process_release :: proc(p: ^Process) -> Error {
- return _process_release(p)
+process_release :: proc(p: ^Process) -> Process_Error {
+ return .None
}
-process_kill :: proc(p: ^Process) -> Error {
- return _process_kill(p)
+process_kill :: proc(p: ^Process) -> Process_Error {
+ return .None
}
-process_signal :: proc(sig: Signal, h: Signal_Handler) -> Error {
- return _process_signal(sig, h)
+process_signal :: proc(p: ^Process, sig: Signal) -> Process_Error {
+ return .None
}
-process_wait :: proc(p: ^Process, t: time.Duration = time.MAX_DURATION) -> (Process_State, Error) {
- return _process_wait(p, t)
+process_wait :: proc(p: ^Process) -> (Process_State, Process_Error) {
+ return {}, .None
}
+
+
+
+
diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin
deleted file mode 100644
index aec838d9d..000000000
--- a/core/os/os2/process_linux.odin
+++ /dev/null
@@ -1,428 +0,0 @@
-//+private
-package os2
-
-import "base:runtime"
-
-import "core:fmt"
-import "core:mem"
-import "core:time"
-import "core:strings"
-import "core:strconv"
-import "core:sys/linux"
-import "core:path/filepath"
-
-_alloc_command_line_arguments :: proc() -> []string {
- res := make([]string, len(runtime.args__), heap_allocator())
- for arg, i in runtime.args__ {
- res[i] = string(arg)
- }
- return res
-}
-
-_exit :: proc "contextless" (code: int) -> ! {
- linux.exit_group(i32(code))
-}
-
-_get_uid :: proc() -> int {
- return int(linux.getuid())
-}
-
-_get_euid :: proc() -> int {
- return int(linux.geteuid())
-}
-
-_get_gid :: proc() -> int {
- return int(linux.getgid())
-}
-
-_get_egid :: proc() -> int {
- return int(linux.getegid())
-}
-
-_get_pid :: proc() -> int {
- return int(linux.getpid())
-}
-
-_get_ppid :: proc() -> int {
- return int(linux.getppid())
-}
-
-Process_Attributes_OS_Specific :: struct {}
-
-_process_find :: proc(pid: int) -> (Process, Error) {
- TEMP_ALLOCATOR_GUARD()
- pid_path := fmt.ctprintf("/proc/%d", pid)
-
- p: Process
- dir_fd: linux.Fd
- errno: linux.Errno
-
- #partial switch dir_fd, errno = linux.open(pid_path, _OPENDIR_FLAGS); errno {
- case .NONE:
- linux.close(dir_fd)
- p.pid = pid
- return p, nil
- case .ENOTDIR:
- return p, .Invalid_Dir
- case .ENOENT:
- return p, .Not_Exist
- }
- return p, _get_platform_error(errno)
-}
-
-_process_get_state :: proc(p: Process) -> (state: Process_State, err: Error) {
- TEMP_ALLOCATOR_GUARD()
-
- stat_name := fmt.ctprintf("/proc/%d/stat", p.pid)
- stat_buf: []u8
- stat_buf, err = _read_entire_pseudo_file(stat_name, temp_allocator())
-
- if err != nil {
- return
- }
-
- idx := strings.last_index_byte(string(stat_buf), ')')
- stats := string(stat_buf[idx + 2:])
-
- // utime and stime are the 12 and 13th items, respectively
- // skip the first 11 items here.
- for i := 0; i < 11; i += 1 {
- stats = stats[strings.index_byte(stats, ' ') + 1:]
- }
-
- idx = strings.index_byte(stats, ' ')
- utime_str := stats[:idx]
-
- stats = stats[idx + 1:]
- stime_str := stats[:strings.index_byte(stats, ' ')]
-
- utime, _ := strconv.parse_int(utime_str, 10)
- stime, _ := strconv.parse_int(stime_str, 10)
-
- // NOTE: Assuming HZ of 100, 1 jiffy == 10 ms
- state.user_time = time.Duration(utime) * 10 * time.Millisecond
- state.system_time = time.Duration(stime) * 10 * time.Millisecond
-
- return
-}
-
-_process_start :: proc(name: string, argv: []string, attr: ^Process_Attributes) -> (child: Process, err: Error) {
- TEMP_ALLOCATOR_GUARD()
-
- dir_fd := linux.AT_FDCWD
- errno: linux.Errno
- if attr != nil && attr.dir != "" {
- dir_cstr := temp_cstring(attr.dir) or_return
- if dir_fd, errno = linux.open(dir_cstr, _OPENDIR_FLAGS); errno != .NONE {
- return child, _get_platform_error(errno)
- }
- }
-
- // search PATH if just a plain name is provided
- executable: cstring
- if !strings.contains_rune(name, '/') {
- path_env := get_env("PATH", temp_allocator())
- path_dirs := filepath.split_list(path_env, temp_allocator())
- found: bool
- for dir in path_dirs {
- executable = fmt.ctprintf("%s/%s", dir, name)
- fail: bool
- if fail, errno = linux.faccessat(dir_fd, executable, linux.F_OK); errno == .NONE && !fail {
- found = true
- break
- }
- }
- if !found {
- // check in cwd to match windows behavior
- executable = fmt.ctprintf("./%s", name)
- fail: bool
- if fail, errno = linux.faccessat(dir_fd, executable, linux.F_OK); errno != .NONE || fail {
- return child, .Not_Exist
- }
- }
- } else {
- executable = temp_cstring(name) or_return
- }
-
- not_exec: bool
- if not_exec, errno = linux.faccessat(dir_fd, executable, linux.F_OK | linux.X_OK); errno != .NONE || not_exec {
- return child, errno == .NONE ? .Permission_Denied : _get_platform_error(errno)
- }
-
- // args and environment need to be a list of cstrings
- // that are terminated by a nil pointer.
- // The first argument is a copy of the executable name.
- cargs := make([]cstring, len(argv) + 2, temp_allocator())
- cargs[0] = executable
- for i := 0; i < len(argv); i += 1 {
- cargs[i + 1] = temp_cstring(argv[i]) or_return
- }
-
- // Use current process's environment if attributes not provided
- env: [^]cstring
- if attr == nil {
- // take this process's current environment
- env = raw_data(export_cstring_environment(temp_allocator()))
- } else {
- cenv := make([]cstring, len(attr.env) + 1, temp_allocator())
- for i := 0; i < len(attr.env); i += 1 {
- cenv[i] = temp_cstring(attr.env[i]) or_return
- }
- env = &cenv[0]
- }
-
- // TODO: This is the traditional textbook implementation with fork.
- // A more efficient implementation with vfork:
- //
- // 1. retrieve signal handlers
- // 2. block all signals
- // 3. allocate some stack space
- // 4. vfork (waits for child exit or execve); In child:
- // a. set child signal handlers
- // b. set up any necessary pipes
- // c. execve
- // 5. restore signal handlers
- //
- stdin_fds: [2]linux.Fd
- stdout_fds: [2]linux.Fd
- stderr_fds: [2]linux.Fd
- if attr != nil && attr.stdin != nil {
- if errno = linux.pipe2(&stdin_fds, nil); errno != .NONE {
- return child, _get_platform_error(errno)
- }
- }
- if attr != nil && attr.stdout != nil {
- if errno = linux.pipe2(&stdout_fds, nil); errno != .NONE {
- return child, _get_platform_error(errno)
- }
- }
- if attr != nil && attr.stderr != nil {
- if errno = linux.pipe2(&stderr_fds, nil); errno != .NONE {
- return child, _get_platform_error(errno)
- }
- }
-
- pid: linux.Pid
- if pid, errno = linux.fork(); errno != .NONE {
- return child, _get_platform_error(errno)
- }
-
- IN :: 1
- OUT :: 0
-
- STDIN :: linux.Fd(0)
- STDOUT :: linux.Fd(1)
- STDERR :: linux.Fd(2)
-
- if pid == 0 {
- // in child process now
- if attr != nil && attr.stdin != nil {
- if linux.close(stdin_fds[IN]) != .NONE { linux.exit(1) }
- if _, errno = linux.dup2(stdin_fds[OUT], STDIN); errno != .NONE { linux.exit(1) }
- if linux.close(stdin_fds[OUT]) != .NONE { linux.exit(1) }
- }
- if attr != nil && attr.stdout != nil {
- if linux.close(stdout_fds[OUT]) != .NONE { linux.exit(1) }
- if _, errno = linux.dup2(stdout_fds[IN], STDOUT); errno != .NONE { linux.exit(1) }
- if linux.close(stdout_fds[IN]) != .NONE { linux.exit(1) }
- }
- if attr != nil && attr.stderr != nil {
- if linux.close(stderr_fds[OUT]) != .NONE { linux.exit(1) }
- if _, errno = linux.dup2(stderr_fds[IN], STDERR); errno != .NONE { linux.exit(1) }
- if linux.close(stderr_fds[IN]) != .NONE { linux.exit(1) }
- }
-
- if errno = linux.execveat(dir_fd, executable, &cargs[OUT], env); errno != .NONE {
- print_error(stderr, _get_platform_error(errno), string(executable))
- panic("execve failed to replace process")
- }
- unreachable()
- }
-
- // in parent process
- if attr != nil && attr.stdin != nil {
- linux.close(stdin_fds[OUT])
- _construct_file(attr.stdin, uintptr(stdin_fds[IN]))
- }
- if attr != nil && attr.stdout != nil {
- linux.close(stdout_fds[IN])
- _construct_file(attr.stdout, uintptr(stdout_fds[OUT]))
- }
- if attr != nil && attr.stderr != nil {
- linux.close(stderr_fds[IN])
- _construct_file(attr.stderr, uintptr(stderr_fds[OUT]))
- }
-
- child.pid = int(pid)
- return child, nil
-}
-
-_process_release :: proc(p: ^Process) -> Error {
- // We didn't allocate...
- return nil
-}
-
-_process_kill :: proc(p: ^Process) -> Error {
- res := linux.kill(linux.Pid(p.pid), .SIGKILL)
- return _get_platform_error(res)
-}
-
-_process_signal :: proc(sig: Signal, h: Signal_Handler) -> Error {
- signo: linux.Signal
- switch sig {
- case .Abort: signo = .SIGABRT
- case .Floating_Point_Exception: signo = .SIGFPE
- case .Illegal_Instruction: signo = .SIGILL
- case .Interrupt: signo = .SIGINT
- case .Segmentation_Fault: signo = .SIGSEGV
- case .Termination: signo = .SIGTERM
- }
-
- sigact: linux.Sig_Action(int)
- old: ^linux.Sig_Action(int) = nil
-
- switch v in h {
- case Signal_Handler_Special:
- switch v {
- case .Default:
- sigact.special = .SIG_DFL
- case .Ignore:
- sigact.special = .SIG_IGN
- }
- case Signal_Handler_Proc:
- sigact.handler = (linux.Sig_Handler_Fn)(v)
- }
-
- return _get_platform_error(linux.rt_sigaction(signo, &sigact, old))
-}
-
-_process_wait :: proc(p: ^Process, t: time.Duration) -> (state: Process_State, err: Error) {
- safe_state :: proc(p: Process, state: Process_State = {}) -> (Process_State, Error) {
- // process_get_state can fail, so we don't want to return it directly.
- if new_state, err := _process_get_state(p); err == nil {
- return new_state, nil
- }
- return state, nil
- }
-
- state.pid = p.pid
-
- options: linux.Wait_Options
- big_if: if t == 0 {
- options += {.WNOHANG}
- } else if t != time.MAX_DURATION {
- ts: linux.Time_Spec = {
- time_sec = uint(t / time.Second),
- time_nsec = uint(t % time.Second),
- }
-
- @static has_pidfd_open: bool = true
-
- // pidfd_open is fairly new, so don't error out on ENOSYS
- pid_fd: linux.Pid_FD
- errno: linux.Errno
- if has_pidfd_open {
- pid_fd, errno = linux.pidfd_open(linux.Pid(p.pid), nil)
- if errno != .NONE && errno != .ENOSYS {
- return state, _get_platform_error(errno)
- }
- }
-
- if has_pidfd_open && errno != .ENOSYS {
- defer linux.close(linux.Fd(pid_fd))
- pollfd: [1]linux.Poll_Fd = {
- {
- fd = linux.Fd(pid_fd),
- events = {.IN},
- },
- }
- for {
- n, e := linux.ppoll(pollfd[:], &ts, nil)
- if e == .EINTR {
- continue
- }
- if e != .NONE {
- return state, _get_platform_error(errno)
- }
- if n == 0 {
- return safe_state(p^, state)
- }
- break
- }
- } else {
- has_pidfd_open = false
- mask: bit_set[0..=63]
- mask += { int(linux.Signal.SIGCHLD) - 1 }
-
- org_sigset: linux.Sig_Set
- sigset: linux.Sig_Set
- mem.copy(&sigset, &mask, size_of(mask))
- errno = linux.rt_sigprocmask(.SIG_BLOCK, &sigset, &org_sigset)
- if errno != .NONE {
- return state, _get_platform_error(errno)
- }
- defer linux.rt_sigprocmask(.SIG_SETMASK, &org_sigset, nil)
-
- // In case there was a signal handler on SIGCHLD, avoid race
- // condition by checking wait first.
- options += {.WNOHANG}
- waitid_options := options + {.WNOWAIT, .WEXITED}
- info: linux.Sig_Info
- errno = linux.waitid(.PID, linux.Id(p.pid), &info, waitid_options, nil)
- if errno == .NONE && info.code != 0 {
- break big_if
- }
-
- loop: for {
- sigset = {}
- mem.copy(&sigset, &mask, size_of(mask))
-
- _, errno = linux.rt_sigtimedwait(&sigset, &info, &ts)
- #partial switch errno {
- case .EAGAIN: // timeout
- return safe_state(p^, state)
- case .EINVAL:
- return state, _get_platform_error(errno)
- case .EINTR:
- continue
- case:
- if int(info.pid) == p.pid {
- break loop
- }
- }
- }
- }
- }
-
- state, _ = safe_state(p^, state)
-
- status: u32
- errno: linux.Errno = .EINTR
- for errno == .EINTR {
- _, errno = linux.wait4(linux.Pid(p.pid), &status, options, nil)
- if errno != .NONE {
- return state, _get_platform_error(errno)
- }
- }
-
- // terminated by exit
- if linux.WIFEXITED(status) {
- p.is_done = true
- state.exited = true
- state.exit_code = int(linux.WEXITSTATUS(status))
- state.success = state.exit_code == 0
- return state, nil
- }
-
- // terminated by signal
- if linux.WIFSIGNALED(status) {
- // NOTE: what's the correct behavior here??
- p.is_done = true
- state.exited = false
- state.exit_code = int(linux.WTERMSIG(status))
- state.success = false
- return state, nil
- }
-
- return safe_state(p^, state)
-}
diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin
deleted file mode 100644
index 4b5e4bc02..000000000
--- a/core/os/os2/process_windows.odin
+++ /dev/null
@@ -1,67 +0,0 @@
-//+private
-package os2
-
-import "core:runtime"
-import "core:time"
-
-_alloc_command_line_arguments :: proc() -> []string {
- return nil
-}
-
-_exit :: proc "contextless" (_: int) -> ! {
- runtime.trap()
-}
-
-_get_uid :: proc() -> int {
- return -1
-}
-
-_get_euid :: proc() -> int {
- return -1
-}
-
-_get_gid :: proc() -> int {
- return -1
-}
-
-_get_egid :: proc() -> int {
- return -1
-}
-
-_get_pid :: proc() -> int {
- return -1
-}
-
-_get_ppid :: proc() -> int {
- return -1
-}
-
-Process_Attributes_OS_Specific :: struct{}
-
-_process_find :: proc(pid: int) -> (Process, Error) {
- return Process{}, nil
-}
-
-_process_get_state :: proc(p: Process) -> (Process_State, Error) {
- return Process_State{}, nil
-}
-
-_process_start :: proc(name: string, argv: []string, attr: ^Process_Attributes) -> (Process, Error) {
- return Process{}, nil
-}
-
-_process_release :: proc(p: ^Process) -> Error {
- return nil
-}
-
-_process_kill :: proc(p: ^Process) -> Error {
- return nil
-}
-
-_process_signal :: proc(sig: Signal, handler: Signal_Handler) -> Error {
- return nil
-}
-
-_process_wait :: proc(p: ^Process, t: time.Duration) -> (Process_State, Error) {
- return Process_State{}, nil
-}