perf: Steam's web helper runs its GPU, audio and zygote work inside one process (#566)

This commit is contained in:
Kurt Himebauch authored and GitHub committed 2026-10-14 01:01:49 -04:00
1 parent 6211faf6bc
commit 3fe03c0a88
5 files changed
+151 -5

No files matched your search

+7 -3
View File
@@ -262,6 +262,7 @@ __attribute__((visibility("hidden"))) void bl_binfmt_before(const char *path, ch
__attribute__((visibility("hidden"))) int bl_binfmt_retry(const char *path, char *const argv[], char *const envp[], int error);
__attribute__((visibility("hidden"))) void bl_binfmt_before_search(const char *file, char *const argv[], char *const envp[]);
__attribute__((visibility("hidden"))) int bl_binfmt_after_search(const char *file, char *const argv[], char *const envp[], int error);
__attribute__((visibility("hidden"))) char *const *bl_webhelper_argv(const char *path, char *const argv[]);
__attribute__((visibility("hidden"))) int bl_binfmt_spawn(pid_t *pid, const char *path, const posix_spawn_file_actions_t *fa,
const posix_spawnattr_t *attr, char *const argv[], char *const envp[],
spawn_fn real);
@@ -308,7 +309,8 @@ static int maybe_answer_lsof(const char *path, char *const argv[]) {
_exit(0);
}
int execve(const char *path, char *const argv[], char *const envp[]) {
int execve(const char *path, char *const argv_in[], char *const envp[]) {
char *const *argv = bl_webhelper_argv(path, argv_in);
static int (*real)(const char *, char *const[], char *const[]);
if (!real) real = (int (*)(const char *, char *const[], char *const[]))dlsym(RTLD_NEXT, "execve");
maybe_answer_lsof(path, argv);
@@ -332,7 +334,8 @@ static int answer_lsof_via_spawn(const char *path, char *const argv[], pid_t *pi
return 0;
}
int execvp(const char *file, char *const argv[]) {
int execvp(const char *file, char *const argv_in[]) {
char *const *argv = bl_webhelper_argv(file, argv_in);
static int (*real)(const char *, char *const[]);
if (!real) real = (int (*)(const char *, char *const[]))dlsym(RTLD_NEXT, "execvp");
maybe_answer_lsof(file, argv);
@@ -341,7 +344,8 @@ int execvp(const char *file, char *const argv[]) {
return bl_binfmt_after_search(file, argv, environ, errno);
}
int execv(const char *path, char *const argv[]) {
int execv(const char *path, char *const argv_in[]) {
char *const *argv = bl_webhelper_argv(path, argv_in);
static int (*real)(const char *, char *const[]);
if (!real) real = (int (*)(const char *, char *const[]))dlsym(RTLD_NEXT, "execv");
maybe_answer_lsof(path, argv);
+73
View File
@@ -0,0 +1,73 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#ifndef WEBHELPER_DEFAULT
#define WEBHELPER_DEFAULT "--no-zygote --in-process-gpu -AudioServiceOutOfProcess"
#endif
static int is_webhelper_browser(const char *path, char *const argv[]) {
if (!path || !argv) return 0;
const char *base = strrchr(path, '/');
base = base ? base + 1 : path;
if (strcmp(base, "steamwebhelper")) return 0;
for (int i = 1; argv[i]; i++)
if (!strncmp(argv[i], "--type=", 7)) return 0;
return 1;
}
static char *join_features(const char *have, const char *add) {
size_t a = have ? strlen(have) : 0, b = strlen(add);
char *out = malloc(a + b + 2);
if (!out) return NULL;
out[0] = 0;
if (a) strcat(strcat(out, have), ",");
return strcat(out, add);
}
__attribute__((visibility("hidden"))) char *const *bl_webhelper_argv(const char *path, char *const argv[]) {
if (!is_webhelper_browser(path, argv)) return argv;
const char *spec = getenv("BL_WEBHELPER_ARGS");
if (!spec || !*spec) spec = WEBHELPER_DEFAULT;
if (!strcmp(spec, "stock")) return argv;
int argc = 0;
while (argv[argc]) argc++;
char *tokens = strdup(spec);
if (!tokens) return argv;
int extra = 0;
for (char *c = tokens; *c; c++)
if (*c == ' ') extra++;
char **out = calloc(argc + extra + 4, sizeof *out);
if (!out) return argv;
const char *enable = NULL, *disable = NULL;
int n = 0;
for (int i = 0; i < argc; i++) {
if (i && !strncmp(argv[i], "--enable-features=", 18)) enable = argv[i] + 18;
else if (i && !strncmp(argv[i], "--disable-features=", 19)) disable = argv[i] + 19;
else out[n++] = argv[i];
}
char *add_enable = NULL, *add_disable = NULL, *save = NULL;
for (char *t = strtok_r(tokens, " ", &save); t; t = strtok_r(NULL, " ", &save)) {
if (t[0] == '+' && t[1]) {
char *joined = join_features(add_enable, t + 1);
free(add_enable);
add_enable = joined;
} else if (t[0] == '-' && t[1] && t[1] != '-') {
char *joined = join_features(add_disable, t + 1);
free(add_disable);
add_disable = joined;
} else if (!strncmp(t, "--", 2)) {
out[n++] = t;
}
}
char *merged;
if (add_enable && (merged = join_features(enable, add_enable))) enable = merged;
if (add_disable && (merged = join_features(disable, add_disable))) disable = merged;
char *flag;
if (enable && (flag = malloc(strlen(enable) + 19))) out[n++] = strcat(strcpy(flag, "--enable-features="), enable);
if (disable && (flag = malloc(strlen(disable) + 20))) out[n++] = strcat(strcpy(flag, "--disable-features="), disable);
out[n] = NULL;
return out;
}
+1 -1
View File
@@ -60,7 +60,7 @@ class BinfmtPreloadTest(unittest.TestCase):
cls.library = cls.tmp / "libbinfmt.so"
subprocess.run(["gcc", "-shared", "-fPIC", "-O2", "-Wall", "-Wextra", "-Werror", "-DBINFMT_TEST",
'-DBINFMT_HANDLER="%s"' % cls.handler, "-o", str(cls.library),
"-pthread"] + [str(PRELOAD / name) for name in ("binfmt.c", "net.c", "udevmon.c", "pathcache.c")] + ["-ldl"],
"-pthread"] + [str(PRELOAD / name) for name in ("binfmt.c", "net.c", "udevmon.c", "pathcache.c", "webhelper.c")] + ["-ldl"],
check=True)
source = cls.tmp / "program.c"
source.write_text(PROGRAM)
+1 -1
View File
@@ -16,7 +16,7 @@ class CdpGuardTest(unittest.TestCase):
def setUpClass(cls):
cls.build = tempfile.TemporaryDirectory()
cls.library = Path(cls.build.name) / "net.so"
subprocess.run(["cc", "-shared", "-fPIC", "-O2", str(SOURCE), str(SOURCE.parent / "binfmt.c"), "-x", "c", "-", "-ldl",
subprocess.run(["cc", "-shared", "-fPIC", "-O2", str(SOURCE), str(SOURCE.parent / "binfmt.c"), str(SOURCE.parent / "webhelper.c"), "-x", "c", "-", "-ldl",
"-o", str(cls.library)],
input=b"int bl_udevmon_stand_in(int fd) { return 0; }", check=True, capture_output=True)
+69
View File
@@ -0,0 +1,69 @@
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest
PRELOAD = Path(__file__).resolve().parents[1] / "linuxfs/preload"
PROGRAM = r"""
#include <stdio.h>
char *const *bl_webhelper_argv(const char *path, char *const argv[]);
int main(int argc, char **argv) {
char *const *out = bl_webhelper_argv(argv[1], argv + 1);
for (int i = 0; out[i]; i++) printf("%s\n", out[i]);
return 0;
}
"""
WEBHELPER = "/root/.local/share/Steam/steamrtarm64/steamwebhelper"
@unittest.skipUnless(shutil.which("cc"), "needs cc")
class WebhelperPreloadTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.tmp = Path(tempfile.mkdtemp())
source = cls.tmp / "program.c"
source.write_text(PROGRAM)
cls.program = cls.tmp / "program"
subprocess.run(["cc", "-O2", "-Wall", "-Werror", "-o", str(cls.program), str(source),
str(PRELOAD / "webhelper.c")], check=True)
@classmethod
def tearDownClass(cls):
shutil.rmtree(cls.tmp, ignore_errors=True)
def argv(self, *args, spec=None):
env = {k: v for k, v in os.environ.items() if k != "BL_WEBHELPER_ARGS"}
if spec is not None:
env["BL_WEBHELPER_ARGS"] = spec
result = subprocess.run([str(self.program), *args], env=env, capture_output=True, text=True, check=True)
return result.stdout.splitlines()
def test_the_browser_process_keeps_its_helpers_in_process(self):
out = self.argv(WEBHELPER, "-lang=en_US", "--enable-features=A", "--no-sandbox", "--disable-features=B,C")
self.assertEqual(out, [WEBHELPER, "-lang=en_US", "--no-sandbox", "--no-zygote", "--in-process-gpu",
"--enable-features=A", "--disable-features=B,C,AudioServiceOutOfProcess"])
def test_feature_lists_are_added_when_steam_passes_none(self):
out = self.argv(WEBHELPER, spec="+X -Y")
self.assertEqual(out, [WEBHELPER, "--enable-features=X", "--disable-features=Y"])
def test_child_processes_and_other_programs_are_left_alone(self):
child = [WEBHELPER, "--type=renderer", "--enable-features=A"]
self.assertEqual(self.argv(*child), child)
other = ["/usr/bin/steam", "--enable-features=A"]
self.assertEqual(self.argv(*other), other)
def test_stock_turns_it_off(self):
args = [WEBHELPER, "--enable-features=A"]
self.assertEqual(self.argv(*args, spec="stock"), args)
def test_an_empty_setting_means_the_default(self):
self.assertIn("--no-zygote", self.argv(WEBHELPER, spec=""))
if __name__ == "__main__":
unittest.main()