mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-27 14:15:09 +00:00
improve error handling; do not report errors from failed execve
This commit is contained in:
@@ -63,7 +63,7 @@ _get_ppid :: proc() -> int {
|
||||
}
|
||||
|
||||
@(private="package")
|
||||
_process_list :: proc(allocator: runtime.Allocator) -> ([]int, Error) {
|
||||
_process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error) {
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
dir_fd: linux.Fd
|
||||
@@ -101,17 +101,21 @@ _process_list :: proc(allocator: runtime.Allocator) -> ([]int, Error) {
|
||||
|
||||
if pid, ok := strconv.parse_int(d_name_str); ok {
|
||||
append(&dynamic_list, pid)
|
||||
} else {
|
||||
return nil, .Invalid_File
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return slice.clone(dynamic_list[:], allocator), nil
|
||||
list, err = slice.clone(dynamic_list[:], allocator)
|
||||
return
|
||||
}
|
||||
|
||||
@(private="package")
|
||||
_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
|
||||
TEMP_ALLOCATOR_GUARD()
|
||||
|
||||
info.pid = pid
|
||||
info.fields = selection
|
||||
|
||||
// Use this so we can use bprintf to make cstrings with less copying.
|
||||
@@ -148,10 +152,15 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
||||
passwd = passwd[strings.index_byte(passwd, ':') + 1:]
|
||||
|
||||
n = strings.index_byte(passwd, ':')
|
||||
if uid, ok := strconv.parse_int(passwd[:n]); ok && uid == int(s.uid) {
|
||||
info.username = strings.clone(username, allocator)
|
||||
uid: int
|
||||
ok: bool
|
||||
if uid, ok = strconv.parse_int(passwd[:n]); ok && uid == int(s.uid) {
|
||||
info.username = strings.clone(username, allocator) or_return
|
||||
break
|
||||
}
|
||||
if !ok {
|
||||
return info, .Invalid_File
|
||||
}
|
||||
|
||||
eol := strings.index_byte(passwd, '\n')
|
||||
if eol == -1 {
|
||||
@@ -184,30 +193,31 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
||||
|
||||
cwd, cwd_err = _read_link_cstr(path_cstr, temp_allocator()) // allowed to fail
|
||||
if cwd_err == nil && .Working_Dir in selection {
|
||||
info.working_dir = strings.clone(cwd, allocator)
|
||||
info.working_dir = strings.clone(cwd, allocator) or_return
|
||||
}
|
||||
}
|
||||
|
||||
if .Executable_Path in selection {
|
||||
if cmdline[0] == '/' {
|
||||
info.executable_path = strings.clone(cmdline[:terminator], allocator)
|
||||
info.executable_path = strings.clone(cmdline[:terminator], allocator) or_return
|
||||
} else if cwd_err == nil {
|
||||
join_paths: [2]string = { cwd, cmdline[:terminator] }
|
||||
info.executable_path = filepath.join(join_paths[:], allocator)
|
||||
}
|
||||
}
|
||||
if .Command_Line in selection {
|
||||
info.command_line = strings.clone(cmdline[:terminator], allocator)
|
||||
info.command_line = strings.clone(cmdline[:terminator], allocator) or_return
|
||||
}
|
||||
|
||||
if .Command_Args in selection {
|
||||
// skip to first arg
|
||||
cmdline = cmdline[terminator + 1:]
|
||||
|
||||
arg_list := make([dynamic]string, allocator)
|
||||
arg_list := make([dynamic]string, allocator) or_return
|
||||
for len(cmdline) > 0 {
|
||||
terminator = strings.index_byte(cmdline, 0)
|
||||
append(&arg_list, strings.clone(cmdline[:terminator], allocator))
|
||||
arg := strings.clone(cmdline[:terminator], allocator) or_return
|
||||
append(&arg_list, arg) or_return
|
||||
cmdline = cmdline[terminator + 1:]
|
||||
}
|
||||
info.command_args = arg_list[:]
|
||||
@@ -230,9 +240,11 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
||||
stats = stats[strings.index_byte(stats, ' ') + 1:]
|
||||
|
||||
if .PPid in selection {
|
||||
ppid_str := stats[strings.index_byte(stats, ' '):]
|
||||
ppid_str := stats[:strings.index_byte(stats, ' ')]
|
||||
if ppid, ok := strconv.parse_int(ppid_str); ok {
|
||||
info.ppid = ppid
|
||||
} else {
|
||||
return info, .Invalid_File
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,9 +253,11 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
||||
for _ in 4..<19 {
|
||||
stats = stats[strings.index_byte(stats, ' ') + 1:]
|
||||
}
|
||||
nice_str := stats[strings.index_byte(stats, ' '):]
|
||||
nice_str := stats[:strings.index_byte(stats, ' ')]
|
||||
if nice, ok := strconv.parse_int(nice_str); ok {
|
||||
info.priority = nice
|
||||
} else {
|
||||
return info, .Invalid_File
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,13 +269,14 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
||||
if env_bytes, env_err := _read_entire_pseudo_file(path_cstr, temp_allocator()); env_err == nil {
|
||||
env := string(env_bytes)
|
||||
|
||||
env_list := make([dynamic]string, allocator)
|
||||
env_list := make([dynamic]string, allocator) or_return
|
||||
for len(env) > 0 {
|
||||
terminator := strings.index_byte(env, 0)
|
||||
if terminator == -1 || terminator == 0 {
|
||||
break
|
||||
}
|
||||
append(&env_list, strings.clone(env[:terminator], allocator))
|
||||
e := strings.clone(env[:terminator], allocator) or_return
|
||||
append(&env_list, e) or_return
|
||||
env = env[terminator + 1:]
|
||||
}
|
||||
info.environment = env_list[:]
|
||||
@@ -417,12 +432,13 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||
}
|
||||
|
||||
if errno = linux.execveat(dir_fd, executable_path, &cargs[0], env); errno != .NONE {
|
||||
print_error(stderr, _get_platform_error(errno), string(executable_path))
|
||||
panic("execve failed to replace process")
|
||||
linux.exit(1)
|
||||
}
|
||||
unreachable()
|
||||
}
|
||||
|
||||
// TODO: We need to come up with a way to detect the execve failure from here.
|
||||
|
||||
process.pid = int(pid)
|
||||
process.handle = PIDFD_UNASSIGNED
|
||||
return
|
||||
@@ -455,8 +471,14 @@ _process_state_update_times :: proc(p: Process, state: ^Process_State) -> (err:
|
||||
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)
|
||||
utime, stime: int
|
||||
ok: bool
|
||||
if utime, ok = strconv.parse_int(utime_str, 10); !ok {
|
||||
return .Invalid_File
|
||||
}
|
||||
if stime, ok = strconv.parse_int(stime_str, 10); !ok {
|
||||
return .Invalid_File
|
||||
}
|
||||
|
||||
// NOTE: Assuming HZ of 100, 1 jiffy == 10 ms
|
||||
state.user_time = time.Duration(utime) * 10 * time.Millisecond
|
||||
|
||||
Reference in New Issue
Block a user