Skip to content

fixed LM_FindProcess() not finding processes running under Proton#280

Closed
krob64 wants to merge 2 commits into
rdbo:masterfrom
krob64:proton-fix
Closed

fixed LM_FindProcess() not finding processes running under Proton#280
krob64 wants to merge 2 commits into
rdbo:masterfrom
krob64:proton-fix

Conversation

@krob64
Copy link
Copy Markdown

@krob64 krob64 commented Jun 7, 2025

Using LM_FindProcess() on a proton process will always fail because /proc/pid/exe links to the wine-preloader.

This can be fixed by reading /cmdline instead of /exe. I tested it with

LM_FindProcess("sekiro.exe", &proc); // proton, game has no arguments
LM_FindProcess("cs2", &proc); // native
LM_FindProcess("Marvel-Win64-Shipping.exe", &proc); // proton, has a bunch of arguments being passed to it

it can find all 3 games as expected.

@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jun 12, 2025

I noticed a change on how the exe path is being read, from /proc//exe to /proc//cmdline.
The process command line doesnt say much about the process itself, because I can start "firefox" by using a command line saying "chromium" or whatever command.
Maybe there could be a cmdline field in the lm_process_t struct for handling more specific cases like this, but I'd have to check if the other platforms support this as well and if it's a viable thing to add.
I'll leave this open for now until I am able to check this further

@krob64
Copy link
Copy Markdown
Author

krob64 commented Jun 12, 2025

The process command line doesnt say much about the process itself, because I can start "firefox" by using a command line saying "chromium" or whatever command.

That is true. It could have some edge-cases, f.e. running a custom script with the name "cs2" before launching the actual cs2, it would then return the pid of your custom script instead of the process you were originally searching for, but i think the same thing happens when reading /exe while two native binaries with the same exact name are running right?

Of the top of my head i can't really think of a better way to cover both finding native and proton processes with a single function. Maybe trying to read /exe first, if no result has been found, retry with /cmdline?

At the end of the day this isn't a huge deal, as one can easily write a function to find a proton process themselves, but it would be nice to have that functionality in libmem.

@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jun 12, 2025

The thing about /exe is that it gives me a full path, so unless the binary is rotating paths, it should be reliable. The find process function currently matches against the end of the path of the executable, so you can either match cs2 or /steamapps/Counter-Strike 2/cs2, so it's something to keep in mind when I'm checking this out later (would be a breaking change, possibly).

To the favor of this change, there are some more cases where matching against the command line is a good idea. For example, it's hard to match against a specific Java process when using /exe because I libmem won't actually know which one of the Java processes is the one I want.

I'm thinking storing the command line might be a good idea (will allow better handling in LM_EnumProcesses).Maybe there could be another function (LM_FindProcessByCmdline or something?)
I'll check this back next week hopefully, have to fix some stuff elsewhere also

@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jun 22, 2025

I think the plan's gonna be:

  • add cmdline field for lm_process_t with size 8192 (max windows size + 1 for null term, on Linux it's much higher but I don't think we need to consider a theoretically possible 100k long cmdline)
  • Consider LM_FindProcessByCmdline (I'm not sure about this, there isn't IMO an obvious way to match against a command line - specially considering cases like Java where the path is not the first arg, or programs that have no order in argument passing)

By at least adding the cmdline field, it would be possible to use LM_EnumProcesses with your own callback to match the cmdline however you'd like. If I can reason with a sane default for LM_FindProcessByCmdline, I'm gonna add it also

@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jun 28, 2025

I just found out (after implementing for both Linux and FreeBSD 😃) that there is no straightforward way to get the command line of processes on Windows.
There is a hacky way that reads process memory, but we don't wanna do that on something like LM_EnumProcesses(), meaning that cmdline should not be a field in the lm_process_t struct.
My new solution would be something like LM_GetCmdLine().

I still have to analyze the viability of a find process by command line function.

@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jun 28, 2025

I added LM_GetCommandLine (still testing it though). This could be done now by doing:

lm_bool_t callback(lm_process_t *proc, lm_void_t *arg)
{
    lm_char_t *cmdline;
    // get cmdline
    cmdline = LM_GetCommandLine(proc);
    if (!cmdline) return LM_TRUE;

    // check if process is proton process
    // using custom matching rules
    // ...
    
    *(lm_process_t *)arg = proc;
    return LM_FALSE;
}

lm_process_t proton_process;
LM_EnumProcesses(callback, &proton_process);

I'm thinking about adding a function for custom process matching, would help in these different cases

EDIT: Oops... There was an oversight in making commands a lm_char_t *: some args have spaces and it will be confusing to match against them. Gotta have to change again.

@rdbo rdbo mentioned this pull request Jul 12, 2025
@rdbo
Copy link
Copy Markdown
Owner

rdbo commented Jul 27, 2025

This is now possible through LM_GetCommandLine

lm_bool_t callback(lm_process_t *proc, lm_void_t *arg)
{
    lm_char_t **cmdline;
    cmdline = LM_GetCommandLine(proc);
    if (!cmdline) return LM_TRUE;

    // check if process is proton process
    // using custom matching rules
    // ...
    
    *(lm_process_t *)arg = proc;
    return LM_FALSE;
}

lm_process_t proton_process;
LM_EnumProcesses(callback, &proton_process);

I'm thinking to make a function for a custom process matcher, but that should be another thing. I believe the main problem here is solved, since you can get the command line and match however you need.

Thanks for letting me know of this problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants