Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Launching app that is allowed to outlive the game #814

Closed
Amzd opened this issue May 27, 2023 · 10 comments · Fixed by #820
Closed

Launching app that is allowed to outlive the game #814

Amzd opened this issue May 27, 2023 · 10 comments · Fixed by #820
Labels
bug Something isn't working Custom command Issues related to launching custom commands

Comments

@Amzd
Copy link

Amzd commented May 27, 2023

System Information

  • SteamTinkerLaunch version: v12.12
  • Distribution: Nobara 37
  • Installation Method: sudo dnf install steamtinkerlaunch

Issue Description

I wish to make sure that OBS is launched when I launch a game, and I do not want to close OBS when I close the game. Currently I have a start script that launches OBS if it does not exist yet:

#!/usr/bin/env bash

# Launch OBS if it is not already launched
# checking for obs with a launch argument so this only works if you have a launch argument in the .desktop file
if [ "$(ps aux | grep "obs --" | awk '{print $11}')" == "grep" ]; then
  (gtk-launch com.obsproject.Studio.desktop) &  
fi

but when I use this as launch script in steamtinkerlaunch and quit the game, steam thinks that OBS is a child of the game process so when I press STOP it quits OBS.

When I run this same script in the steam launch option "obs.sh" & %command% it works the way I want (steam does not care if it is still running after the game closed and I can run a different game) but I would like to do this for all my games and steamtinkerlaunch seemed like the way to go.

I have tried all the setsid, disown combinations I could imagine but could not get it to work in start script.

Any help is very much appreciated.

@Amzd Amzd added the bug Something isn't working label May 27, 2023
@sonic2kk
Copy link
Owner

sonic2kk commented May 27, 2023

I spent a while investigating this and wrote up a lot of replies which I eventually removed and re-wrote, because I actually figured out the problem (after an unhealthy amount of caffeine ingestion): When Steam launches a process, any process (including STL), it launches a "reaper" program with it. As far as I am aware, this is launched after %command%, and this is important to note.

Reaper is some kind of Steam process that is designed to manage application processes launched from Steam, and then properly "kill" them (hence "reaper" 😉). On game launch, Steam automatically starts the Reaper process. This was not always the case, from looking at the code I can see that the assumed behaviour before was that Reaper was started with the Steam Linux Runtime. I have confirmed that this is no longer the case as Reaper launches with any Proton game.

If you manually kill the Reaper process, and then exit a game from the game process itself, such as from an in-game quit button, then Steam will keep a forked custom command set in SteamTinkerLaunch open, and it will revert back to showing the "Play" button. However, with Reaper killed, if you press the "Quit" button from Steam, it will hang at "Stopping". This is true with and without SteamTinkerLaunch.


So the question is: Why does your example with the launch options work? Well as far as I can tell, when you run your script with the launch option described, Steam has not started the "reaper" process yet, and so the process is likely unaware of any forked background processes. Any processes forked after reaper has started are likely tracked somehow and Steam knows to kill them. My guess would be that they got more strict with this because of the Steam Deck, and want to ensure as many game-related processes are killed as possible.

So since reaper only starts after %command%, your example works. But when you use SteamTinkerLaunch and then quit a game from Steam, reaper will "reap" the forked process as well.


SteamTinkerLaunch does have an option to enable/disable reaper, but this was written before Reaper was enabled by default for all Steam launches. The toggle manually tried to launch the reaper command if it could find it, but now Steam will always launch it, so this toggle effectively does nothing. Really the option would now need to attempt to kill the reaper process if disabled, and that should give you the functionality you're looking for, with two caveats:

  1. The "Stop" button from Steam will not work if Reaper is killed, games will have to be quit either by you manually (on KDE you can use Ctrl+Alt+Esc which allows you to click a window to kill a process) or from a quit button inside of the game itself.
  2. This script would need to be set as a forked custom command for each game. There is currently to my knowledge no way to set a global script for every game, but this could be added I think if you think it would be useful :-)

It may also be possible for you to amend your script to kill the reaper process. I don't know how to implement this myself (though I'll need to figure it out to implement this in STL), so I can't give any tips right now. Though I will say, I have seen processes on my system which have reaper in the name, so make sure to check for an exact match. You'd probably want to run this outside of your if that you showed, as Steam will start reaper with each game launch (irrespective of STL)


tl;dr Steam's reaper process which starts per-game is the culprit. This is now launched by Steam with the %command% and anything before this will not use reaper. Though STL does have an option to disable reaper, it needs updated to account for this "new" behaviour because previously it was only launched as part of the Steam Linux Runtime.

Thanks for opening this issue and bringing this to my attention. Fork custom command is supposed to do exactly what you said and to some extent it does because it keeps the process alive after SteamTinkerLaunch closes, but Steam is more "greedy" now with the processes it tracks as game processes and so Steam itself thinks the game is a child process. STL's fork logic does use &, but Reaper doesn't seem to care.

The solution here in the short-term for you is to kill reaper I think. In the longer-term, STL needs to fix its logic around toggling the reaper process.

@sonic2kk
Copy link
Owner

#815 is up which checks if Reaper is running and kills it if USEREAP is 0 (if the checkbox on the game menu is off). This will hopefully solve the main issue here of Steam closing forked processes with the game. It worked in my tests at least :-)

The other issue mentioned of having to do this per-game is still present. You'll also have to make sure the reaper toggle is off per-game. In all honesty, for your use-case, it is probably more straightforward to just add your launch options to Steam if this is the only use-case. Adding this script for each game and ensuring reaper is disabled might be a lot of work to do for every game, and while a global script option could be added, Reaper will still always be enabled by default.

@sonic2kk sonic2kk added the Custom command Issues related to launching custom commands label May 27, 2023
@Amzd
Copy link
Author

Amzd commented May 27, 2023

Thank you so much for such a detailed response! Do I understand correctly that STL is launched after the %command%, so it could never launch start scripts before Steam tracks them with reaper?

I know it would've been faster to just set the script as launch option in steam in all my games but never spend an hour doing manual work when you can spend 4 hours automating it is what I always say haha.

@sonic2kk
Copy link
Owner

Thank you so much for such a detailed response! Do I understand correctly that STL is launched after the %command%, so it could never launch start scripts before Steam tracks them with reaper?

Yes, at least as far as I can tell. With Proton games, STL is used as a compatibility tool, so %command% is actually the SteamTinkerLaunch start command. This command is in SteamTinkerLaunch's toolmanifest.vdf file. I am not sure which one Steam actually picks to be honest but %command% will actually refer to some form of ./steamtinkerlaunch. And as far as I can tell from the couple of hours I spent investigating the problem here, Steam will start reaper as soon as it starts a process.

I would guess Steam does this so that programs with messy processes (e.g. the EA Link app) have as much chance of being closed as possible when the "Close" button is pressed. Since on Steam Deck, Valve have a string that notes when a program needs to be exited manually, they'd want to make especially sure that any processes launched after the "Play" button is pressed actually get killed when the "Close" button is pressed (Steam assumes any processes launched by pressing "Play" are game-related processes, which is true for most situations I would say 😅).

If there is a way to tell Steam to not use reaper, maybe through a command line switch, I am unaware of it. Actually, I am not even sure Reaper is that well documented since it's afaik a proprietary internal Steam component.

I know it would've been faster to just set the script as launch option in steam in all my games but never spend an hour doing manual work when you can spend 4 hours automating it is what I always say haha.

I take the same mindset, no idea why there are people like us but here we are :-) You are of course still free to use STL!


If you'd like you could add some logic like below to your script, or try out #815 if you're willing to use a git branch.

if pgrep -x "reaper"; then
    pkill -9 "reaper"
fi

The PR basically does the same thing. It hasn't been merged yet as it is pending some further testing, and I'll probably change some wording. How reaper worked previously was a bit different and because the change in behaviour is related to some Steam client changes, some legacy code will need stripped out and some wording will need to be changed (ex: we don't check for reaper to *enable( it anymore as Steam always gives it, instead we check for and remove it, so the checkbox should probably be reworded and the force option will do nothing so it can be removed).


Either way, good luck with your tinkering, whichever way you do it! We can leave this issue open until #815 is merged into STL, or if you feel further changes are needed we can leave this open until all pending discussion is resolved :-)

@Amzd
Copy link
Author

Amzd commented May 27, 2023

I like the functionality of reaper, and definitely want it to close all the EA bullshit that starts up when you play one of their games, so killing reaper just for OBS will not do. Thank you for the information.

some legacy code will need stripped out and some wording will need to be changed

There is an option to "Keep STL open after after game exit" which doesn't stop it from getting culled by reaper if user clicks STOP. That is expected of course but maybe the description could include a bit more detail. I could not find the reaper toggle you mentioned to check what its behavior would be without it.

@sonic2kk
Copy link
Owner

I like the functionality of reaper, and definitely want it to close all the EA bullshit that starts up when you play one of their games, so killing reaper just for OBS will not do. Thank you for the information.

This toggle is per-game, so you can keep reaper enabled for EA games but close it for non-EA games :-)

I could not find the reaper toggle you mentioned to check what its behavior would be without it.

The reaper toggle is grouped with the Steam Linux Runtime options.

image

@sonic2kk
Copy link
Owner

There are some conflicts with #815 as a result of some Vortex SLR changes (the code for SLR and reaper is shared), so I'll need to resolve those first as well as doing a bit more testing around these changes, to ensure the default behaviour of not killing reaper is preserved. This feature should hopefully be in soon though, and the initial request of keeping forked custom commands opened when a game is quit should be resolved :-)

@sonic2kk
Copy link
Owner

sonic2kk commented May 28, 2023

The bulk of the work for #815 is now done, but it needs a hell of a lot of further testing. There were a lot of changes to some delicate parts of the launch command building, and after resolving the merge conflicts, I want to be 110% sure nothing is broken from this PR.

I will do lots of further testing on my own, other users are also free to test. Provided nothing is broken from that PR, I will merge it soon enough.

@sonic2kk
Copy link
Owner

sonic2kk commented May 30, 2023

After testing, #815 seems stable enough to merge. However I noticed one thing. When using native Linux games with STL, you use STL like steamtinkerlaunch %command%. However the problem with this is that because steamtinkerlaunch goes before %command%, the reaper process does not start until after you press "Play" from SteamTinkerLaunch! This confirms that I suspected earlier, where reaper does not start until after %command%.

Reaper is still not passed from the commandline, so instead we'll need some way to kill reaper after a game has opened. This will be interesting... Oh, reaper is passed from the commandline it seems: /home/emma/.local/share/Steam/ubuntu12_32/reaper appears in the native Linux launch command for my test game (To the Moon). It might still be more reliable to try and "wait" for reaper and kill it, though.

@sonic2kk
Copy link
Owner

sonic2kk commented Jun 3, 2023

Redid the original PR, now we only have to kill Reaper for Proton games because when using a native game, Reaper is correctly removed with the existing logic as it comes as part of %command%.

This issue should now be resolved :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Custom command Issues related to launching custom commands
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants