mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 03:21:08 +00:00
Session stop: kill guest processes proot lost, and cap the session log
Twice today a session's Xwayland aborted from one thread ("The futex
facility returned an unexpected error code"), proot lost the tracee, and
the process lived on reparented to init: proot's seccomp filter, with no
tracer left, answers ENOSYS, so Xwayland's main loop logged
"WaitForSomething(): poll: Function not implemented" until something killed
it - 9 GB after Dolphin, 13 GB after PPSSPP. --kill-on-exit and the tree
sweep only reach what proot still traces, and the straggler sweep ran only
at the next session's start.
Now a session stop also kills every process of ours whose executable lives
in the Linux runtime, and bannerlator-session keeps only the first
BL_LOG_CAP bytes (256 MB) of session.log, draining the rest so a writer
that filled it is not killed by SIGPIPE.
This commit is contained in:
1 parent
9aed4e7a5c
commit
9d13b238bd
2 files changed
+29
-1
No files matched your search
@@ -741,6 +741,30 @@ class SessionService : Service() {
|
||||
* behind, still holding the Wayland socket and the audio server the next session needs. They
|
||||
* are our uid, so they are ours to kill.
|
||||
*/
|
||||
/**
|
||||
* Every process of ours still running a program out of the Linux runtime once proot is gone.
|
||||
* proot's --kill-on-exit and the tree sweep only reach what proot still traces; a tracee it
|
||||
* lost - an Xwayland that aborted from one thread and then looped on a syscall proot's own
|
||||
* seccomp filter, with no tracer left, answers ENOSYS - survives both, reparented to init,
|
||||
* and wrote 9 GB of one line into the session log before anything killed it.
|
||||
*/
|
||||
private fun killGuestLeftovers() {
|
||||
val me = android.os.Process.myPid()
|
||||
val rootfs = try { File(filesDir, "linuxfs").canonicalPath } catch (e: Exception) { return } + "/"
|
||||
val procs = File("/proc").listFiles { f -> f.name.all { it.isDigit() } } ?: return
|
||||
var killed = 0
|
||||
for (proc in procs) {
|
||||
val pid = proc.name.toIntOrNull() ?: continue
|
||||
if (pid == me) continue
|
||||
// Another uid's exe is not ours to read; a process already gone has none.
|
||||
val exe = try { File(proc, "exe").canonicalPath } catch (e: Exception) { continue }
|
||||
if (!exe.startsWith(rootfs)) continue
|
||||
android.os.Process.killProcess(pid)
|
||||
killed++
|
||||
}
|
||||
if (killed > 0) Log.w(TAG, "killed $killed guest process(es) proot no longer tracked")
|
||||
}
|
||||
|
||||
private fun killStragglers() {
|
||||
val me = android.os.Process.myPid()
|
||||
val procs = File("/proc").listFiles { f -> f.name.all { it.isDigit() } } ?: return
|
||||
@@ -917,6 +941,7 @@ class SessionService : Service() {
|
||||
Thread({
|
||||
auxiliary.forEach { (pid, started) -> teardown(pid, started) }
|
||||
if (prootPid > 1) teardown(prootPid)
|
||||
killGuestLeftovers()
|
||||
finishSessionStop(status)
|
||||
}, "session-teardown").start()
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,10 @@ if [ -n "${BL_LOG:-}" ] && [ -z "${BL_INSIDE:-}" ]; then
|
||||
if [ "$(stat -c %s "$BL_LOG" 2>/dev/null || echo 0)" -gt 8388608 ]; then
|
||||
mv -f "$BL_LOG" "$BL_LOG.1"
|
||||
fi
|
||||
exec >>"$BL_LOG" 2>&1
|
||||
# A guest looping on an error writes gigabytes in minutes (an Xwayland proot had lost track of
|
||||
# managed 9 GB of one line in 19 min): the log keeps its first BL_LOG_CAP bytes and the rest is
|
||||
# drained, not refused - a writer that filled it must not die of SIGPIPE.
|
||||
exec > >({ head -c "${BL_LOG_CAP:-268435456}" >>"$BL_LOG"; cat >/dev/null; }) 2>&1
|
||||
echo "== bannerlator-session $(date) mode=$mode $*"
|
||||
echo "== uid=$(id -u) size=${BL_WIDTH:-?}x${BL_HEIGHT:-?} fps=${BL_FPS:-0} icd=${VK_ICD_FILENAMES:-none}"
|
||||
echo "== gamescope: $(gamescope --version 2>&1 | head -1) at $(command -v gamescope)"
|
||||
|
||||
Reference in new issue
Block a user