Init script called multiple times at boot on TP-Link v9, launching duplicate rayhunter instances cause ioctl failure
- Dominant language
- Rust
- Stars
- 5.8k
- Forks
- 490
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 23
Description
### Prerequisites
- [x] I have read [CONTRIBUTING.md](https://github.com/EFForg/rayhunter/blob/main/CONTRIBUTING.md)
### Bug Report Details
VIBE CODE WARNING
Rayhunter v0.10.1 logs appear broken on TP-Link M7350 v9 out of the box. The log shows 11 retries followed by `DiagInitError`. A working instance is actually running but its log was overwritten. It appears that the init is called multiple times each boot. Each call launches a new rayhunter-daemon via `start-stop-daemon -b`. The first instance claims the MD session (mask=31) and works. Subsequent instances fail the ioctl (MD session already taken) and their log truncation (`> rayhunter.log`) overwrites the first instance's success log. The user sees only `-1` failures even though a working instance exists.
The port triggering rule that starts rayhunter:
```javascript
triggerPort: "$(/etc/init.d/rayhunter_daemon start &)"
```
might be evaluated multiple times as network interfaces come up, each time executing the init script. Each call launches a new `rayhunter-daemon` because `start-stop-daemon` uses `--startas /bin/sh` without `--exec`
Related: #676, #683
## Log output (stock init script)
```
R A Y H U N T E R 🐳
[2026-02-19T19:08:15Z INFO rayhunter_daemon] Using configuration for device: Tplink
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 1 times, retrying in 100ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 2 times, retrying in 200ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 3 times, retrying in 400ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 4 times, retrying in 800ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:16Z INFO rayhunter::diag_device] Diag device initialization failed 5 times, retrying in 1.6s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:18Z INFO rayhunter::diag_device] Diag device initialization failed 6 times, retrying in 3.2s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:21Z INFO rayhunter::diag_device] Diag device initialization failed 7 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:27Z INFO rayhunter::diag_device] Diag device initialization failed 8 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:32Z INFO rayhunter::diag_device] Diag device initialization failed 9 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:37Z INFO rayhunter::diag_device] Diag device initialization failed 10 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:42Z INFO rayhunter::diag_device] Diag device initialization failed 11 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:47Z ERROR rayhunter::diag_device] Failed to initialize diag device after 30s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
Error: DiagInitError(InitializationFailed("DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1"))
```
## Workaround
Add `--exec /data/rayhunter/rayhunter-daemon` so `start-stop-daemon` detects the already-running instance:
```diff
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
+ --exec /data/rayhunter/rayhunter-daemon \
--startas /bin/sh -- -c "RUST_LOG=info exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
```
## Environment
- **Device**: TP-Link M7350 v9.0
- **Firmware**: 9.0.3 Build 241219 Rel.1089n
- **Modem**: Quectel EC25EUC (firmware EC25EUCGAR08A01M2G_OCPU_01.001.04)
- **Chip**: Qualcomm MDM9607
- **Rayhunter**: v0.10.1
- **Host OS**: Windows 11
EDIT Original context
## Summary
On the TP-Link M7350 v9.0, rayhunter fails to initialize `/dev/diag` on every boot with `DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1`. The cause is system daemons that hold `/dev/diag` open at boot, blocking rayhunter's ioctl. Killing these processes before starting rayhunter resolves the issue.
Related: #676, #683
## Device
- TP-Link M7350 v9.0, firmware 9.0.3 Build 241219
- Rayhunter v0.10.1
## Log output (stock init script)
```
R A Y H U N T E R 🐳
[2026-02-19T19:08:15Z INFO rayhunter_daemon] Using configuration for device: Tplink
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 1 times, retrying in 100ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 2 times, retrying in 200ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 3 times, retrying in 400ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:15Z INFO rayhunter::diag_device] Diag device initialization failed 4 times, retrying in 800ms: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:16Z INFO rayhunter::diag_device] Diag device initialization failed 5 times, retrying in 1.6s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:18Z INFO rayhunter::diag_device] Diag device initialization failed 6 times, retrying in 3.2s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:21Z INFO rayhunter::diag_device] Diag device initialization failed 7 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:27Z INFO rayhunter::diag_device] Diag device initialization failed 8 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:32Z INFO rayhunter::diag_device] Diag device initialization failed 9 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:37Z INFO rayhunter::diag_device] Diag device initialization failed 10 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:42Z INFO rayhunter::diag_device] Diag device initialization failed 11 times, retrying in 5s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
[2026-02-19T19:08:47Z ERROR rayhunter::diag_device] Failed to initialize diag device after 30s: Failed to initialize /dev/diag: DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1
Error: DiagInitError(InitializationFailed("DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code -1"))
```
**Note:** Even though the log reports initialization failure, rayhunter was still producing QMDL entries with data. However, as with #676, the quality/reliability of that data is uncertain.
## Root cause
On the M7350 v9.0, several system daemons hold `/dev/diag` open at boot. While they hold the device, rayhunter's `DIAG_IOCTL_SWITCH_LOGGING` ioctl fails. The 30-second retry window is not enough — these processes run permanently.
The processes I found holding `/dev/diag` on my device:
- `diagrebootapp` (respawned by `/etc/inittab`)
- `services_monitor` (respawned by `/etc/inittab`)
- `qti`
- `qmuxd`
- `MCM_MOBILEAP_ConnectionManager`
- `quectel_daemon`
- `mobile`
- `ql_manager_server`
- `thermal-engine`
## Solution
Modified the init script to kill these processes before starting rayhunter. Two of them (`diagrebootapp`, `services_monitor`) are respawned by inittab, so a double-kill is needed: kill, wait for inittab to respawn, kill again. After rayhunter claims `/dev/diag`, the cellular daemons are restarted so connectivity is restored.
## Log output (modified init script)
```
R A Y H U N T E R 🐳
[2026-02-19T19:11:03Z INFO rayhunter_daemon] Using configuration for device: Tplink
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] Diag device initialization succeeded after 0 retries
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] retrieving diag logging capabilities...
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 329 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 1
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 298 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 4
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 140 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 5
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 168 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 7
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 122 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 10
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 73 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 11
[2026-02-19T19:11:03Z WARN rayhunter::diag] warning: 72 leftover bytes when parsing Message
[2026-02-19T19:11:03Z INFO rayhunter::diag_device] enabled logging for log type 13
[2026-02-19T19:11:03Z INFO rayhunter_daemon] Starting Diag Thread
[2026-02-19T19:11:03Z INFO rayhunter_daemon] Starting UI
[2026-02-19T19:11:03Z INFO rayhunter_daemon::display::tplink] fallback to framebuffer
[2026-02-19T19:11:03Z INFO rayhunter_daemon] Starting Key Input service
[2026-02-19T19:11:03Z INFO rayhunter_daemon] create shutdown thread
[2026-02-19T19:11:03Z INFO rayhunter_daemon] spinning up server
[2026-02-19T19:11:03Z INFO rayhunter_daemon] The orca is hunting for stingrays...
[2026-02-19T19:11:03Z WARN rayhunter_daemon::battery] Failed to get battery status: Error parsing file to determine battery level
```
**Note:** The battery warning only appears at startup. Battery status updates correctly on subsequent checks.
## Init script fix (diff against installer-generated stock script)
```diff
--- a/dist/scripts/rayhunter_daemon
+++ b/dist/scripts/rayhunter_daemon
@@ -6,8 +6,30 @@
case "$1" in
start)
echo -n "Starting rayhunter: "
(mount /dev/mmcblk0p1 /media/sdcard || true) 2>&1 | tee /tmp/rayhunter-mount.log
+ # Kill all processes that hold /dev/diag and create competing MD sessions.
+ # diagrebootapp and services_monitor are respawned by inittab, so we must
+ # kill them, wait for init to respawn them, then kill again.
+ killall -9 services_monitor 2>/dev/null || true
+ killall -9 diagrebootapp 2>/dev/null || true
+ killall -9 MCM_MOBILEAP_ConnectionManager 2>/dev/null || true
+ killall -9 qti 2>/dev/null || true
+ killall -9 qmuxd 2>/dev/null || true
+ killall -9 quectel_daemon 2>/dev/null || true
+ killall -9 mobile 2>/dev/null || true
+ killall -9 ql_manager_server 2>/dev/null || true
+ killall -9 thermal-engine 2>/dev/null || true
+ sleep 1
+ killall -9 services_monitor 2>/dev/null || true
+ killall -9 diagrebootapp 2>/dev/null || true
+ killall -9 MCM_MOBILEAP_ConnectionManager 2>/dev/null || true
+ sleep 1
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
--startas /bin/sh -- -c "RUST_LOG=info exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
+ # Restart killed daemons so cellular connectivity is restored
+ sleep 5
+ /etc/init.d/chgrp-diag start 2>/dev/null || true
+ /etc/init.d/quectel_daemon start 2>/dev/null || true
+ /etc/init.d/thermal-engine start 2>/dev/null || true
+ /etc/init.d/mobile-mgr start 2>/dev/null || true
+ /etc/init.d/start_ql_manager_server_le start 2>/dev/null || true
+ /etc/init.d/start_MCM_MOBILEAP_ConnectionManager_le start 2>/dev/null || true
echo "done"
;;
```
## Environment
- **Device**: TP-Link M7350 v9.0
- **Firmware**: 9.0.3 Build 241219 Rel.1089n
- **Modem**: Quectel EC25EUC (firmware EC25EUCGAR08A01M2G_OCPU_01.001.04)
- **Chip**: Qualcomm MDM9607
- **Rayhunter**: v0.10.1
- **Host OS**: Windows 11
Contributor guide
Assessment
This issue has not been assessed yet.