Skip to content

Commit 9706d15

Browse files
committed
Fix sd-bus thread-safety crash in Linux tray (#405)
sd-bus objects are not thread-safe, but the event-loop thread (sd_bus_process) and the JVM threads driving the sni_tray_set_*/ sni_tray_item_* mutators (sd_bus_emit_*) accessed tray->bus with no synchronization. Under frequent updates an emit races with an in-flight sd_bus_process and trips 'Assertion !bus->current_slot ... Aborting'. - Add a bus_lock mutex serializing all sd_bus_* access and the tray state it touches: held across setup, each sd_bus_process batch and teardown, and acquired by every public mutator. - Defer user callbacks (click / menu) through a queue flushed by the event loop after releasing bus_lock, so upcalls into Kotlin can re-enter the mutators without deadlocking against the caller's lock. - Add a standalone C concurrency regression test that aborts on the old code and passes on the fixed code.
1 parent 03cd59a commit 9706d15

3 files changed

Lines changed: 289 additions & 26 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
# Build and run the issue #405 concurrency regression test.
3+
# Runs the stress harness several times under a private D-Bus session.
4+
# Exit 0 only if every run completes without crashing.
5+
6+
set -u
7+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8+
SDBUS_CFLAGS=$(pkg-config --cflags libsystemd)
9+
SDBUS_LIBS=$(pkg-config --libs libsystemd)
10+
BIN="$SCRIPT_DIR/test_sni_concurrency"
11+
12+
echo "Compiling concurrency test..."
13+
gcc -O2 -g -fPIC -Wall -Wextra -Wno-unused-parameter \
14+
-I "$SCRIPT_DIR" $SDBUS_CFLAGS \
15+
"$SCRIPT_DIR/sni.c" "$SCRIPT_DIR/test_sni_concurrency.c" \
16+
$SDBUS_LIBS -lpthread -lm -o "$BIN" || { echo "compile failed"; exit 2; }
17+
18+
RUNS="${1:-5}"
19+
rc=0
20+
for i in $(seq 1 "$RUNS"); do
21+
echo "--- run $i/$RUNS ---"
22+
dbus-run-session -- "$BIN"
23+
status=$?
24+
if [ $status -ne 0 ]; then
25+
echo "FAIL: run $i exited with status $status (signal $((status-128)) if >128)"
26+
rc=1
27+
break
28+
fi
29+
done
30+
31+
rm -f "$BIN"
32+
if [ $rc -eq 0 ]; then
33+
echo "PASS: all $RUNS runs completed without crash"
34+
fi
35+
exit $rc

0 commit comments

Comments
 (0)