fix: clean stale JACK SHM before client creation in profile handler
CI / test (push) Has been cancelled
CI / test (push) Has been cancelled
jack.Client('pi-multifx') fails with server_error (0x21) when stale
jack_sem.0_default_pi-multifx segments remain in /dev/shm from a
previous client instance. This commonly happens after a profile change
(buffer+rate) because:
1. stop_jack() kills jackd and cleans SHM
2. start_jack() starts new JACK server
3. Old process's JackAudioClient.__del__ (garbage collection) recreates
the pi-multifx semaphore in /dev/shm
4. jack_client.start() → jack.Client('pi-multifx') finds stale SHM
and fails with server_error → no pi-multifx ports → NAM never
called → 0% nam_cpu → 'nam is dying'
Fix:
- Clean /dev/shm/jack* in profile handler right before jack_client.start()
- JackAudioClient.start() also retries once with SHM cleanup on
server_error, so other callers are also protected.
This commit is contained in:
+18
-1
@@ -882,7 +882,24 @@ class JackAudioClient:
|
||||
self._client = jack.Client(self._client_name)
|
||||
except jack.JackOpenError as exc:
|
||||
logger.error("Cannot open JACK client: %s", exc)
|
||||
return
|
||||
# Stale SHM from a previous client instance can cause
|
||||
# server_error (0x21). Clean and retry once.
|
||||
if "server_error" in str(exc) or "0x21" in str(exc):
|
||||
try:
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
for p in Path("/dev/shm").glob("jack*"):
|
||||
if p.is_dir():
|
||||
shutil.rmtree(p, ignore_errors=True)
|
||||
else:
|
||||
p.unlink(missing_ok=True)
|
||||
logger.info("Cleaned stale JACK SHM, retrying client creation...")
|
||||
self._client = jack.Client(self._client_name)
|
||||
except Exception as retry_exc:
|
||||
logger.error("JACK client retry also failed: %s", retry_exc)
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
# Register capture ports
|
||||
self._inports.clear()
|
||||
|
||||
@@ -1748,6 +1748,20 @@ class WebServer:
|
||||
target_profile["rate"],
|
||||
)
|
||||
|
||||
# Clean stale client SHM before creating new JACK client.
|
||||
# The old process's jack.Client __del__ can recreate the
|
||||
# pi-multifx semaphore after stop_jack() cleaned it.
|
||||
try:
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
for p in Path("/dev/shm").glob("jack*"):
|
||||
if p.is_dir():
|
||||
shutil.rmtree(p, ignore_errors=True)
|
||||
else:
|
||||
p.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Restart JACK audio client
|
||||
if jack_client:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user