diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin index a0815ca7d..1480e66b5 100644 --- a/core/os/os2/process_linux.odin +++ b/core/os/os2/process_linux.odin @@ -162,7 +162,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator } } - cmdline_if: if selection & {.Working_Dir, .Command_Line, .Command_Args, .Executable_Path} != {} { + cmdline_if: if selection & {.Working_Dir, .Command_Line, .Command_Args} != {} { strings.builder_reset(&path_builder) strings.write_string(&path_builder, "/proc/") strings.write_int(&path_builder, pid) @@ -178,12 +178,12 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator terminator := strings.index_byte(cmdline, 0) assert(terminator > 0) - command_line_exec := cmdline[:terminator] + // command_line_exec := cmdline[:terminator] // Still need cwd if the execution on the command line is relative. cwd: string cwd_err: Error - if .Working_Dir in selection || (.Executable_Path in selection && command_line_exec[0] != '/') { + if .Working_Dir in selection { strings.builder_reset(&path_builder) strings.write_string(&path_builder, "/proc/") strings.write_int(&path_builder, pid) @@ -199,39 +199,6 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator } } - if .Executable_Path in selection { - if cwd_err == nil { - info.executable_path = strings.clone(command_line_exec, allocator) or_return - info.fields += {.Executable_Path} - } else { - break cmdline_if - } - /* - NOTE(Jeroen): - - This old version returns the wrong executable path for things like `bash` or `sh`, - for whom `/proc//cmdline` will just report "bash" or "sh", - resulting in misleading paths like `$PWD/sh`, even though that executable doesn't exist there. - - A way to "fix" this would be to invoke `which ` or scour the $PATH variable, but a better way - would be preferred. - - To be fair, `htop` also suffers from this problem and will list `bash`, `tmux`, `xfce4-panel` as just their - executable name in the command line column. So I think we shouldn't prepend the current directory when an executable is - found in the $PATH, which is what seems to be happening here. - - if command_line_exec[0] == '/' { - info.executable_path = strings.clone(command_line_exec, allocator) or_return - info.fields += {.Executable_Path} - } else if cwd_err == nil { - info.executable_path = join_path({cwd, command_line_exec}, allocator) or_return - info.fields += {.Executable_Path} - } else { - break cmdline_if - } - */ - } - if selection & {.Command_Line, .Command_Args} != {} { // skip to first arg //cmdline = cmdline[terminator + 1:] @@ -344,6 +311,30 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator } } + if .Executable_Path in selection { + /* + NOTE(Jeroen): + + The old version returned the wrong executable path for things like `bash` or `sh`, + for whom `/proc//cmdline` will just report "bash" or "sh", + resulting in misleading paths like `$PWD/sh`, even though that executable doesn't exist there. + + Thanks to Yawning for suggesting `/proc/self/exe`. + */ + + strings.builder_reset(&path_builder) + strings.write_string(&path_builder, "/proc/") + strings.write_int(&path_builder, pid) + strings.write_string(&path_builder, "/exe") + + if exe_bytes, exe_err := _read_link(strings.to_string(path_builder), temp_allocator()); exe_err == nil { + info.executable_path = strings.clone(string(exe_bytes), allocator) or_return + info.fields += {.Executable_Path} + } else { + err = exe_err + } + } + if .Environment in selection { strings.builder_reset(&path_builder) strings.write_string(&path_builder, "/proc/")