fix: Steam's Browse buttons work when another app holds port 8080 with Decky enabled (#1798)

This commit is contained in:
MaxsTechReview authored and GitHub committed 2026-10-29 21:22:14 -04:00
1 parent 23bb361006
commit 26e2f26ec9
2 files changed
+97 -8

No files matched your search

@@ -101,6 +101,22 @@ if [ -z "${BL_INSIDE:-}" ]; then
if [ "${BL_ZRAM:-0}" = 1 ]; then printf 0 > /tmp/.bl-zram; else rm -f /tmp/.bl-zram; fi
fi
steam_devtools() {
_bl_cdp=()
if [ -f "$steam_root/.cef-enable-remote-debugging" ]; then
if timeout 5 python3 -c 'import socket, sys
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("127.0.0.1", int(sys.argv[1])))' "$1" 2>/dev/null; then
BL_CDP_PORT=$1
return 0
fi
echo "== steam: port $1 is held by another app; Decky cannot load this session and Steam's devtools use another port"
fi
BL_CDP_PORT=$((20000 + RANDOM % 30000))
_bl_cdp=(-cef-enable-debugging -devtools-port "$BL_CDP_PORT")
}
steam_update_stuck() {
local stamp
stamp=$(stat -c '%n %Y %s' "${steam_root:-}"/package/*.installed 2>/dev/null)
@@ -983,14 +999,9 @@ case $mode in
echo "== Decky: installed loader architecture is unsupported by this guest; not starting"
fi
fi
_bl_cdp=()
if [ -f "$steam_root/.cef-enable-remote-debugging" ]; then
export BL_CDP_PORT=8080
else
export BL_CDP_PORT=$((20000 + RANDOM % 30000))
_bl_cdp=(-cef-enable-debugging -devtools-port "$BL_CDP_PORT")
fi
if [ -f "$HOME/.droiddeck-decky-enabled" ] && [ "${decky_arch:-}" = x86_64 ]; then
steam_devtools 8080
export BL_CDP_PORT
if [ -f "$HOME/.droiddeck-decky-enabled" ] && [ "${decky_arch:-}" = x86_64 ] && [ ${#_bl_cdp[@]} = 0 ]; then
echo "== steam: devtools port $BL_CDP_PORT left open for the x86_64 Decky loader"
else
export BL_CDP_GUARD=$BL_CDP_PORT
+78
View File
@@ -0,0 +1,78 @@
import re
import shlex
import socket
import subprocess
import tempfile
import unittest
from pathlib import Path
SESSION = Path(__file__).resolve().parents[1] / "linuxfs/overlay/usr/local/bin/droiddeck-session"
def devtools_function():
match = re.search(r"^steam_devtools\(\) \{\n.*?^\}\n", SESSION.read_text(), re.M | re.S)
return match.group(0) if match else None
class SteamDevtoolsPortTest(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
def free_port(self):
with socket.socket() as sock:
sock.bind(("127.0.0.1", 0))
return sock.getsockname()[1]
def choose(self, port):
function = devtools_function()
self.assertIsNotNone(function, "droiddeck-session has no steam_devtools()")
script = function + "steam_root=%s\nsteam_devtools %d\n" % (shlex.quote(str(self.root)), port)
script += 'echo "port=$BL_CDP_PORT"\necho "args=${_bl_cdp[*]}"\n'
out = subprocess.run(["bash", "-c", script], capture_output=True, text=True, timeout=30, check=True).stdout
lines = out.splitlines()
port_line = next(l for l in lines if l.startswith("port="))
args_line = next(l for l in lines if l.startswith("args="))
return int(port_line[5:]), args_line[5:].split(), out
def test_without_remote_debugging_steam_gets_a_private_port(self):
port, args, _ = self.choose(self.free_port())
self.assertEqual(["-cef-enable-debugging", "-devtools-port", str(port)], args)
self.assertTrue(20000 <= port < 50000)
def test_remote_debugging_keeps_the_fixed_port_when_it_is_free(self):
(self.root / ".cef-enable-remote-debugging").touch()
fixed = self.free_port()
port, args, out = self.choose(fixed)
self.assertEqual(fixed, port)
self.assertEqual([], args)
self.assertNotIn("held by another app", out)
def test_a_fixed_port_another_app_holds_falls_back_to_a_private_one(self):
(self.root / ".cef-enable-remote-debugging").touch()
with socket.socket() as other:
other.bind(("127.0.0.1", 0))
other.listen(1)
taken = other.getsockname()[1]
port, args, out = self.choose(taken)
self.assertNotEqual(taken, port)
self.assertEqual(["-cef-enable-debugging", "-devtools-port", str(port)], args)
self.assertIn("held by another app", out)
def test_a_fixed_port_bound_without_listening_also_falls_back(self):
(self.root / ".cef-enable-remote-debugging").touch()
with socket.socket() as other:
other.bind(("127.0.0.1", 0))
taken = other.getsockname()[1]
port, args, out = self.choose(taken)
self.assertNotEqual(taken, port)
self.assertEqual(["-cef-enable-debugging", "-devtools-port", str(port)], args)
def test_the_x86_64_decky_exemption_only_covers_the_fixed_port(self):
text = SESSION.read_text()
self.assertIn('[ "${decky_arch:-}" = x86_64 ] && [ ${#_bl_cdp[@]} = 0 ]', text)
if __name__ == "__main__":
unittest.main()