-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Do/Undo Commands fail to work after executing a certain amount of times #1456
Comments
Can confirm this happens on my machine as well. Windows 10 x64 19045.3208
|
Also seeing this issue. My repro case is: Global prep:
App:
The first 6 times I stream this "game", it works just fine. The 7th time, it fails. Afterwards, all prep/global prep commands fail. In a more complicated example (python script prep command), I'm getting the same exit code as reported above: "-1073741801". According to this source, this exit code is an out of memory error. I've confirmed via Process Explorer that none of the prep commands are being left behind after they run. But maybe Sunshine is somehow leaking child process memory? Restarting Sunshine allows another 6 runs, until a restart is needed again. This is consistent. Windows 10 Pro Build 19045.3208. |
As a workaround, I wrote the following python script to restart Sunshine every 3 streams. It's not ideal, but it does prevent Sunshine from locking up. import argparse
import os
import pathlib
import subprocess
import sys
import time
import win32serviceutil # requires pywin32 from pip
# The number of streams after which to restart Sunshine. If you have a large number of prep commands,
# you may need to decrease this.
CONSECUTIVE_STREAMS = 3
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
MEMORY_PATH = os.path.join(SCRIPT_DIR, '.memory')
def read_memory() -> int:
if not os.path.isfile(MEMORY_PATH):
return 0
return int(pathlib.Path(MEMORY_PATH).read_text().strip())
def write_memory(value: int):
with open(MEMORY_PATH, 'w') as file:
print(value, file=file)
def normal_handler():
count = read_memory() + 1
if count >= CONSECUTIVE_STREAMS:
# Wait sufficiently long for other undo scripts to finish, and for the stream to end.
time.sleep(5)
win32serviceutil.RestartService('Sunshine Service')
write_memory(0)
else:
write_memory(count)
def detached_handler():
# Spawn background process to restart Sunshine. This will allow Sunshine to finish up the stream before we restart it
detached_flags = 0x00000008
subprocess.Popen([sys.executable, __file__, 'normal'], creationflags=detached_flags)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
prog='Sunshine Restarter',
description=f"This script is used to restart Sunshine after {CONSECUTIVE_STREAMS} consecutive streams. This is to work around a bug where prep commands will fail after running so many times."
)
subparsers = parser.add_subparsers(required=True, help='What action to take.')
normal_parser = subparsers.add_parser('normal', help='Normal mode. Will restart Sunshine if consecutive stream count has been reached.')
normal_parser.set_defaults(handler=normal_handler)
detached_parser = subparsers.add_parser('detached', help='Detached mode. Will spawn detached process to do the restart. This is so the stream can finish up before we restart.')
detached_parser.set_defaults(handler=detached_handler)
args = parser.parse_args()
args.handler() It should be run as a global undo prep command: {"do":"","undo":"<path to python exe> <path to where you saved the script> detached","elevated":"true"} |
This seems related to the environment block that is passed into ec = impersonate_current_user(user_token, [&]() {
std::wstring env_block = create_environment_block(env);
ret = CreateProcessAsUserW(user_token,
NULL,
(LPWSTR) wcmd.c_str(),
NULL,
NULL,
!!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES),
creation_flags,
env_block.data(), // here
start_dir.empty() ? NULL : start_dir.c_str(),
(LPSTARTUPINFOW) &startup_info,
&process_info);
}); If I pass a NULL environment block instead (that is, just let it inherit from Sunshine's process), I'm unable to reproduce the issue. I don't see anything wrong with the implementation, at least according to all of the documentation and code examples I've read online. As a test, I wrote an implementation that does the following instead of passing an environment block:
This method also fails after the same number of prep command executions. The return code this time is 259 (ERROR_NO_MORE_ITEMS: No more data is available.), and I see |
@kirksaunders Good find, I believe I found a fix and submitted a PR. Can you test and confirm for me? |
@Nonary Thanks to your PR I found the root cause: // For the PATH variable, we will merge the values together
if (boost::iequals(env_name, "PATH")) {
env[env_name] = env_val + ";" + env[env_name].to_string();
BOOST_LOG(info) << "PATH now has size = " << env[env_name].to_string().size();
} Since A quick debug log to show the length of
Your change remedies this, but in turn breaks the path concatenation. I think the proper solution here is to make
I can take up this task, or feel free to do so if you want. Related bug: the error code when running undo commands is in the wrong scope (source). This means that one undo command that fails with an error code causes all following undo commands to fail. This error code should be instantiated/declared inside of the for loop, so that each undo command starts with an empty error code object. Might as well include this fix too. |
Another option would be just assigning a new variable without using &, and having boost clone the environment via its copy constructor. I tried that on my PR and that seemed to work as well. |
This issue has been fixed and will be available in the next release. |
Is there an existing issue for this?
Is your issue described in the documentation?
Is your issue present in the nightly release?
Describe the Bug
Sunshine will fail to execute do/undo commands after executing them a certain number of times, appears to be intermitent.
To replicate the bug:
Add an app with the following do/undo commands:
Start the debug stream, end it at least 3 times. By the fourth time it ends, Sunshine will be unable to execute any commands (command, detached, do, undo, does not matter) because of error code -1073741801
When putting this error code through the Windows Error Lookup, this implies it is a memory problem (page file ran out) however I have adjusted my page file to 80GB in size and the issue still remains and is persistent.
There is no solution other than rebooting the sunshine service.
Expected Behavior
That it does not permanently break until you restart the Sunshine process.
Additional Context
Desktop (with prep commands disabled) works in this state still.
Host Operating System
Windows
Operating System Version
11
Architecture
64 bit
Sunshine commit or version
0.20
Package
Linux - AppImage
GPU Type
Nvidia
GPU Model
4090
GPU Driver/Mesa Version
536.67
Capture Method (Linux Only)
No response
Config
Apps
No response
Relevant log output
The text was updated successfully, but these errors were encountered: