improve error handling; do not report errors from failed execve

This commit is contained in:
jason
2024-07-30 08:45:53 -04:00
parent a5fa93e06d
commit a03dffcd1a
+39 -17
View File
@@ -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