AprilNEA / AprilNEA/OpenLogi

[Bug]: macOS agent pauses device I/O until restart when a screen/session wake notification never arrives

Open
#1,281 2 comments 0 reactions 0 assignees View on GitHub
platform: macos type: bug
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
2d 5h
Merged PRs (30d)
172

Description

### Pre-flight checklist

- [x] I searched existing issues and this is not a duplicate.
- [x] I am on the latest release (0.8.3).
- [x] Logi Options+ is not installed.

### Which part of OpenLogi?

Both (agent + GUI)

### OpenLogi version

0.8.3

### Operating system

macOS

### OS version & architecture

macOS 26.6.2 (Tahoe), Apple Silicon (M5 Max). MacBook Pro in clamshell mode: lid closed, one external 3840x1600 display as the main display.

### Device model

MX Master 3

### How is the device connected?

Logitech Unifying receiver (046d:c52b)

### Affected area(s)

- [x] Device discovery / detection

### What happened?

The agent paused all HID access and never resumed. `openlogi list` showed the receiver's paired slots as `○ Unknown device` for 66 minutes while I was actively using the machine (the mouse still moved through macOS's own driver, OpenLogi just saw nothing). Restarting the agent fixed it instantly.

`crates/openlogi-agent/src/tray.rs` closes the device-I/O gate on `NSWorkspaceWillSleep` / `ScreensDidSleep` / `SessionDidResignActive` and reopens it only on `ScreensDidWake` / `SessionDidBecomeActive`. Those are edges, and the workspace notification center guarantees neither delivery nor pairing. If a suspend edge arrives and its partner does not, the suspend mask keeps that bit for the life of the process. There is no timeout and no re-read of any state, so the agent cannot notice that its belief disagrees with reality.

Expected: the agent works out that the display and session are back and resumes on its own.

### Steps to reproduce

Not reliably reproducible on demand, since it depends on a dropped notification. The sequence I observed:

1. MacBook in clamshell, one external display as main; MX Master 3 on a Unifying receiver.
2. Leave the machine until it locks; come back and unlock.
3. The display reconfigures at unlock (a ~1 s off/on blink in `pmset -g log`).
4. Keep working. `openlogi list` now reports the paired slots as `○ Unknown device` and the GUI shows no devices, indefinitely.
5. `launchctl kickstart -k gui/$UID/org.openlogi.agent.service` and everything is immediately correct again.

### Logs

`~/.local/state/openlogi/agent.2026-09-05.log` (UTC):

```
2026-09-05T23:04:20.461468Z INFO openlogi_agent::lifecycle: openlogi-agent started
2026-09-05T23:04:20.492010Z INFO openlogi_agent::tray: display/session resumed — enabling device I/O
2026-09-05T23:04:39.393454Z INFO openlogi_agent::tray: display/session suspended — pausing device I/O
... no further display/session line for the next 66 minutes ...
2026-09-05T23:45:34.156297Z WARN tarpc::server: Requests stream errored out: could not flush the transport: Broken pipe (os error 32)
2026-09-05T23:46:39.958208Z WARN tarpc::server: Requests stream errored out: could not flush the transport: Broken pipe (os error 32)
2026-09-05T23:47:03.108966Z WARN tarpc::server: Requests stream errored out: could not flush the transport: Broken pipe (os error 32)
```

The three `Broken pipe` warnings are three `openlogi list` runs in that window. The suspend line does not say which notification produced it, so the log cannot tell a dropped `ScreensDidWake` from a dropped `SessionDidBecomeActive`.

`pmset -g log` (local time, UTC-7) at the same instant:

```
2026-09-05 16:04:29 -0700 Display is turned on
2026-09-05 16:04:39 -0700 Display is turned off
2026-09-05 16:04:40 -0700 Display is turned on
```

16:04:39 local is 23:04:39 UTC, the same second as the suspend line: a one-second blink at unlock with no wake notification after it. The unified log for that window was not retained, so I can't prove which notification was dropped, but either way the gate has no path back.

`openlogi list` during the outage:

```
Unifying Receiver (E3C196DA, vid=046d pid=c52b)
├─ slot 1 ○ Unknown device (mouse, wpid=4069, battery=—)
└─ slot 2 ○ Unknown device (mouse, wpid=4082, battery=—)
```

### Related

The same log shows the relaunch half of #952 from the other side: during an earlier 2.5 h display sleep the agent was relaunched 27 times (the watchdog exit in #952), and every relaunch logged `display/session resumed — enabling device I/O`. That line is only reachable when the startup snapshot decides the display is awake, so `CGDisplayIsAsleep(CGMainDisplayID())` answered `false` for the whole blank that `NSWorkspaceScreensDidSleep` had reported correctly a second earlier. With the lid shut the external panel is the only online display, so reading the full display list gives the same answer, and on Apple Silicon `IODisplayWrangler` has no `IOPowerManagement` dictionary to read instead. So each relaunched agent resumed HID probing behind a dark panel.

I have a fix for both halves; PR to follow.

### macOS permissions

- [x] Accessibility
- [x] Input Monitoring

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in crates/openlogi-agent/src/tray.rs and trace the suspend/resume notification handling, including the startup state check described in the issue. Reproduce or inspect the logged suspend sequence, then verify that device I/O resumes after a missing wake notification and that relaunch behavior does not resume probing while the display is asleep.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.