hopefully does not lose keyboard control any more for users
This commit is contained in:
@@ -35,7 +35,7 @@ from gi.repository import Gst, GstWebRTC, GstSdp, GLib
|
||||
import requests
|
||||
import websockets
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format='[gst_agent] %(message)s', stream=sys.stderr)
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s [gst_agent] %(message)s', stream=sys.stderr)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# ── Configuration ─────────────────────────────────────────────────────────────
|
||||
@@ -345,16 +345,33 @@ class CSSStreamAgent:
|
||||
def css_watchdog():
|
||||
# If cstrike_win64.exe crashes (e.g. Wine c0000409 stack overrun), the
|
||||
# stream keeps running but shows a black screen forever with no recovery.
|
||||
# This watchdog detects the crash and relaunches CSS directly via revLoader,
|
||||
# the same way start.sh does on initial boot. gst_agent keeps running and
|
||||
# will simply start capturing the relaunched game once it renders.
|
||||
# This watchdog detects the crash and triggers a restart.
|
||||
#
|
||||
# IMPORTANT: this must NOT relaunch CSS directly itself. Doing so
|
||||
# (a bare `wine revLoader.exe` Popen call) created a second, uncoordinated
|
||||
# restart authority alongside the signaling server's own kill+relaunch
|
||||
# logic (manual button / scheduled 5h restart). If both fired close
|
||||
# together, two separate Wine processes could end up racing to launch
|
||||
# CSS, producing duplicate/orphaned windows — xdotool's window search
|
||||
# would then target an arbitrary one, causing keyboard input to land on
|
||||
# a stale/backgrounded window while video (which captures the whole X
|
||||
# display, not a specific window) kept working fine. That mismatch is
|
||||
# exactly the "mouse/video fine, keyboard dead" symptom that was
|
||||
# reported after a watchdog relaunch overlapped with a manual restart.
|
||||
#
|
||||
# So instead we just notify the signaling server, which has the single
|
||||
# authoritative kill+relaunch implementation (performCssRestart) shared
|
||||
# by the manual restart button, the scheduled 5-hour restart, and this
|
||||
# watchdog — never more than one restart in flight at a time.
|
||||
#
|
||||
# We only start watching once CSS has been seen alive at least once, to
|
||||
# avoid racing its initial startup. Require several consecutive misses to
|
||||
# avoid false positives during a normal controller-triggered relaunch
|
||||
# (the signaling server kills+relaunches CSS on controller change).
|
||||
home = os.path.expanduser('~')
|
||||
revloader = os.path.join(home, 'Counter-Strike Source', 'revLoader.exe')
|
||||
# avoid false positives during a normal controller-triggered handoff.
|
||||
restart_url = SIG_URL.replace('ws://', 'http://').replace('wss://', 'https://')
|
||||
if not restart_url.endswith('/'):
|
||||
restart_url += '/'
|
||||
restart_url += 'webclient-force-restart'
|
||||
|
||||
seen_alive = False
|
||||
missing_count = 0
|
||||
while True:
|
||||
@@ -381,17 +398,14 @@ def css_watchdog():
|
||||
# 4 consecutive misses (~20s) — long enough to not collide with the
|
||||
# signaling server's own kill+relaunch cycle on controller change.
|
||||
if missing_count >= 4:
|
||||
log.error('CSS appears crashed — relaunching revLoader')
|
||||
log.error('CSS appears crashed — requesting restart from signaling server')
|
||||
try:
|
||||
env = dict(os.environ, DISPLAY=DISPLAY)
|
||||
subprocess.Popen(['wine', revloader], env=env,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
log.info('revLoader relaunched by watchdog')
|
||||
resp = requests.post(restart_url, timeout=5)
|
||||
log.info(f'restart request sent to {restart_url}, status={resp.status_code}')
|
||||
except Exception as e:
|
||||
log.error(f'watchdog relaunch failed: {e}')
|
||||
# Reset so we give the relaunched game time to come up before
|
||||
# counting misses again.
|
||||
log.error(f'watchdog restart request failed: {e}')
|
||||
# Reset so we give the restart time to complete before counting
|
||||
# misses again.
|
||||
seen_alive = False
|
||||
missing_count = 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user