mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +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")
|
@(private="package")
|
||||||
_process_list :: proc(allocator: runtime.Allocator) -> ([]int, Error) {
|
_process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error) {
|
||||||
TEMP_ALLOCATOR_GUARD()
|
TEMP_ALLOCATOR_GUARD()
|
||||||
|
|
||||||
dir_fd: linux.Fd
|
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 {
|
if pid, ok := strconv.parse_int(d_name_str); ok {
|
||||||
append(&dynamic_list, pid)
|
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")
|
@(private="package")
|
||||||
_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
|
_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
|
||||||
TEMP_ALLOCATOR_GUARD()
|
TEMP_ALLOCATOR_GUARD()
|
||||||
|
|
||||||
|
info.pid = pid
|
||||||
info.fields = selection
|
info.fields = selection
|
||||||
|
|
||||||
// Use this so we can use bprintf to make cstrings with less copying.
|
// 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:]
|
passwd = passwd[strings.index_byte(passwd, ':') + 1:]
|
||||||
|
|
||||||
n = strings.index_byte(passwd, ':')
|
n = strings.index_byte(passwd, ':')
|
||||||
if uid, ok := strconv.parse_int(passwd[:n]); ok && uid == int(s.uid) {
|
uid: int
|
||||||
info.username = strings.clone(username, allocator)
|
ok: bool
|
||||||
|
if uid, ok = strconv.parse_int(passwd[:n]); ok && uid == int(s.uid) {
|
||||||
|
info.username = strings.clone(username, allocator) or_return
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if !ok {
|
||||||
|
return info, .Invalid_File
|
||||||
|
}
|
||||||
|
|
||||||
eol := strings.index_byte(passwd, '\n')
|
eol := strings.index_byte(passwd, '\n')
|
||||||
if eol == -1 {
|
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
|
cwd, cwd_err = _read_link_cstr(path_cstr, temp_allocator()) // allowed to fail
|
||||||
if cwd_err == nil && .Working_Dir in selection {
|
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 .Executable_Path in selection {
|
||||||
if cmdline[0] == '/' {
|
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 {
|
} else if cwd_err == nil {
|
||||||
join_paths: [2]string = { cwd, cmdline[:terminator] }
|
join_paths: [2]string = { cwd, cmdline[:terminator] }
|
||||||
info.executable_path = filepath.join(join_paths[:], allocator)
|
info.executable_path = filepath.join(join_paths[:], allocator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if .Command_Line in selection {
|
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 {
|
if .Command_Args in selection {
|
||||||
// skip to first arg
|
// skip to first arg
|
||||||
cmdline = cmdline[terminator + 1:]
|
cmdline = cmdline[terminator + 1:]
|
||||||
|
|
||||||
arg_list := make([dynamic]string, allocator)
|
arg_list := make([dynamic]string, allocator) or_return
|
||||||
for len(cmdline) > 0 {
|
for len(cmdline) > 0 {
|
||||||
terminator = strings.index_byte(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:]
|
cmdline = cmdline[terminator + 1:]
|
||||||
}
|
}
|
||||||
info.command_args = arg_list[:]
|
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:]
|
stats = stats[strings.index_byte(stats, ' ') + 1:]
|
||||||
|
|
||||||
if .PPid in selection {
|
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 {
|
if ppid, ok := strconv.parse_int(ppid_str); ok {
|
||||||
info.ppid = ppid
|
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 {
|
for _ in 4..<19 {
|
||||||
stats = stats[strings.index_byte(stats, ' ') + 1:]
|
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 {
|
if nice, ok := strconv.parse_int(nice_str); ok {
|
||||||
info.priority = nice
|
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 {
|
if env_bytes, env_err := _read_entire_pseudo_file(path_cstr, temp_allocator()); env_err == nil {
|
||||||
env := string(env_bytes)
|
env := string(env_bytes)
|
||||||
|
|
||||||
env_list := make([dynamic]string, allocator)
|
env_list := make([dynamic]string, allocator) or_return
|
||||||
for len(env) > 0 {
|
for len(env) > 0 {
|
||||||
terminator := strings.index_byte(env, 0)
|
terminator := strings.index_byte(env, 0)
|
||||||
if terminator == -1 || terminator == 0 {
|
if terminator == -1 || terminator == 0 {
|
||||||
break
|
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:]
|
env = env[terminator + 1:]
|
||||||
}
|
}
|
||||||
info.environment = env_list[:]
|
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 {
|
if errno = linux.execveat(dir_fd, executable_path, &cargs[0], env); errno != .NONE {
|
||||||
print_error(stderr, _get_platform_error(errno), string(executable_path))
|
linux.exit(1)
|
||||||
panic("execve failed to replace process")
|
|
||||||
}
|
}
|
||||||
unreachable()
|
unreachable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: We need to come up with a way to detect the execve failure from here.
|
||||||
|
|
||||||
process.pid = int(pid)
|
process.pid = int(pid)
|
||||||
process.handle = PIDFD_UNASSIGNED
|
process.handle = PIDFD_UNASSIGNED
|
||||||
return
|
return
|
||||||
@@ -455,8 +471,14 @@ _process_state_update_times :: proc(p: Process, state: ^Process_State) -> (err:
|
|||||||
stats = stats[idx + 1:]
|
stats = stats[idx + 1:]
|
||||||
stime_str := stats[:strings.index_byte(stats, ' ')]
|
stime_str := stats[:strings.index_byte(stats, ' ')]
|
||||||
|
|
||||||
utime, _ := strconv.parse_int(utime_str, 10)
|
utime, stime: int
|
||||||
stime, _ := strconv.parse_int(stime_str, 10)
|
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
|
// NOTE: Assuming HZ of 100, 1 jiffy == 10 ms
|
||||||
state.user_time = time.Duration(utime) * 10 * time.Millisecond
|
state.user_time = time.Duration(utime) * 10 * time.Millisecond
|
||||||
|
|||||||
Reference in New Issue
Block a user