mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
Every Electron AppImage hung without a window or crashed at its first page. Four causes, each enough on its own: - The session preload's hooks found the real functions with dlsym(RTLD_NEXT). Before glibc 2.34 a thread's first dlsym callocs, and Chromium's PartitionAlloc calls syscall() from inside its first malloc: the allocator waited for itself. On older glibc (the x86 runtime's 2.31) next.c now walks the libraries after the preload with no allocation and picks each function's default version, as glibc 2.36 does; the old lookup handed realpath() and posix_spawn() their compat versions, and realpath(path, NULL) failed. arm64 keeps dlsym. - libpci's sysfs backend exits when /sys/bus/pci/devices is listable but a device's files are not (a RedMagic's PCIe root port), taking every Chromium GPU process with it. An empty directory is bound over it on devices where that happens. - FEX_OUTPUTLOG=stderr made FEX log to its own duplicate of descriptor 2. Chromium dup2()s its IPC socket onto that low number in each child it starts, then lists /proc/self/fd, which FEX logs into the socket. Empty, FEX writes to descriptor 2 itself. - The tracer preload served every /proc/<pid>/status as a memfd, which is open for writing. Chromium hands each renderer its status as a read-only file and checks that it is one. Only a process's own status (pid, tid, self, thread-self) is rewritten now.
68 lines
2.8 KiB
C
68 lines
2.8 KiB
C
/*
|
|
* The Steam client's own screen, in a Follow screen session.
|
|
*
|
|
* With two Xwayland servers the client sizes them through GAMESCOPE_XWAYLAND_MODE_CONTROL
|
|
* ({server, width, height, allow_super_res} on the root window): the games' server (1) to a game's
|
|
* Game Resolution, and its own (0) to what it recommends for the display - 1920x1080 on a Fold's
|
|
* 2448x1848 inner panel. From then on it reads that 16:9 size back as the display's "native" one,
|
|
* so its interface and every game it starts are 16:9 with bars on a near-square panel, and stay so
|
|
* when the phone folds onto the cover screen.
|
|
*
|
|
* gamescope already keeps server 0 at the output's size and resizes it when the output changes (a
|
|
* Steam Deck docking; here, the app resizing the output as the phone folds and unfolds). So in a
|
|
* Follow screen session (BL_FOLLOW_OUTPUT=1) a request for server 0 is dropped and the client's
|
|
* screen stays the panel's; requests for the games' servers pass through untouched. Any other
|
|
* session, and any other property, is passed straight on.
|
|
*/
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
__attribute__((visibility("hidden"))) void *bl_next(const char *name);
|
|
|
|
/* Xlib's types, without needing its headers in the build image. */
|
|
typedef struct _XDisplay Display;
|
|
typedef unsigned long Atom;
|
|
typedef unsigned long Window;
|
|
typedef int Bool;
|
|
|
|
typedef int (*change_property_fn)(Display *, Window, Atom, Atom, int, int, const unsigned char *, int);
|
|
typedef Atom (*intern_atom_fn)(Display *, const char *, Bool);
|
|
|
|
static int following(void) {
|
|
static int cached = -1;
|
|
if (cached < 0) {
|
|
const char *v = getenv("BL_FOLLOW_OUTPUT");
|
|
cached = v && v[0] == '1';
|
|
}
|
|
return cached;
|
|
}
|
|
|
|
int XChangeProperty(Display *dpy, Window w, Atom property, Atom type, int format, int mode,
|
|
const unsigned char *data, int nelements) {
|
|
static change_property_fn real;
|
|
if (!real) real = (change_property_fn)bl_next("XChangeProperty");
|
|
if (!real) return 0;
|
|
if (following() && format == 32 && nelements == 4 && data) {
|
|
static intern_atom_fn intern;
|
|
static Display *atom_dpy;
|
|
static Atom mode_control;
|
|
if (!intern) intern = (intern_atom_fn)bl_next("XInternAtom");
|
|
/* Atoms belong to a connection; the client's is the one that writes this. */
|
|
if (intern && atom_dpy != dpy) {
|
|
mode_control = intern(dpy, "GAMESCOPE_XWAYLAND_MODE_CONTROL", 1);
|
|
atom_dpy = dpy;
|
|
}
|
|
/* Format-32 property data is an array of long in Xlib. */
|
|
const long *v = (const long *)data;
|
|
if (mode_control && property == mode_control && v[0] == 0) {
|
|
static int said;
|
|
if (said++ < 3)
|
|
fprintf(stderr, "== steam: kept its screen at the panel's size (it asked for %ldx%ld)\n", v[1], v[2]);
|
|
return 1;
|
|
}
|
|
}
|
|
return real(dpy, w, property, type, format, mode, data, nelements);
|
|
}
|