Skip to content

Commit 34641b2

Browse files
committed
2 parents 22d111b + 21c7204 commit 34641b2

2 files changed

Lines changed: 15 additions & 15 deletions

File tree

docs/llms-full.txt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9257,7 +9257,7 @@ JNI reflection metadata must include the bridge class:
92579257

92589258
---
92599259

9260-
# Media Control (Linux + macOS + Windows)
9260+
# Media Control
92619261

92629262
OS-level media controls (play/pause, next/previous, seek, metadata) for your desktop app, exposed through a single cross-platform Kotlin API:
92639263

@@ -11621,19 +11621,6 @@ The `scheduler` module registers background tasks with the OS so they run even w
1162111621

1162211622
[^min-interval]: Enforced at request construction — see [Minimum interval](#minimum-interval) for the exact `IllegalArgumentException` behavior.
1162311623

11624-
### Orphan cleanup after uninstall
11625-
11626-
Users uninstall apps without thinking about background scheduled tasks. Without explicit cleanup, the OS would keep firing schedules pointing to a missing executable forever. Nucleus handles this differently per platform:
11627-
11628-
- **Linux** and **Windows** — the scheduler does *not* register the application binary directly. It writes a tiny wrapper script (`<taskId>.sh` in `nucleus/scheduler//scripts/` on Linux, `<taskId>.vbs` in `%LOCALAPPDATA%\nucleus\scheduler\\scripts\` on Windows) and registers *that* with systemd / Task Scheduler. The wrapper checks whether the application binary still exists before invoking it. If it's gone, the wrapper **self-destructs**: it disables and deletes the systemd `.timer` / `.service` units (Linux) or removes the COM tasks under `\Nucleus\\` (Windows) via the same Schedule.Service API used to create them, deletes the persisted metadata, and finally removes itself. Net result: the next time the OS triggers a task whose app has been uninstalled, the schedule cleans itself up and stops firing.
11629-
- **macOS** — **no automatic cleanup.** Unlike the Linux/Windows wrapper trick, the agent's `ProgramArguments` points directly at the application binary so the entry stays visible under its real name in System Settings → "Allow in the Background". The cost: when the user trashes the .app bundle, the orphaned `.plist` in `~/Library/LaunchAgents/` is **never** reclaimed by macOS, and launchd keeps attempting to spawn the missing binary forever — throttled by `ThrottleInterval` (10 s by default), logging `cannot spawn` to `system.log` on every attempt. SMAppService (macOS 13+) does not eliminate this either, and Apple ships no guidance for "graceful uninstall of a LaunchAgent" — the macOS ecosystem treats orphaned LaunchAgents as a known limitation that an explicit cleanup step has to handle. The mitigation Nucleus offers is **in-app**: call `DesktopTaskScheduler.cancelAll()` from your app's settings ("Disable background tasks") or from any in-app sign-out / reset flow — this unloads the agents and removes the plists cleanly while the binary is still around. If the user does a plain drag-to-trash without that step, the orphan leaks; the leftover plist then has to be removed manually:
11630-
11631-
```bash
11632-
rm ~/Library/LaunchAgents/io.github.kdroidfilter.nucleus..<taskId>.plist
11633-
```
11634-
11635-
The failure mode in the meantime is the well-known throttled-log-spam — not a crash and not a security or correctness issue.
11636-
1163711624
## Installation
1163811625

1163911626
```kotlin
@@ -12203,6 +12190,19 @@ Creates systemd user service and timer units in `~/.config/systemd/user/` (respe
1220312190

1220412191
Registers tasks under `\Nucleus\\` via a JNI bridge (`WindowsTaskSchedulerJni`) that calls the Task Scheduler 2.0 COM API (`ITaskService`, `ITaskFolder`, `ITaskDefinition`) — no `schtasks.exe` subprocess. Supports periodic, daily, weekly, logon, and one-shot triggers natively. The task action runs the [self-destructing wrapper script](#orphan-cleanup-after-uninstall) via `wscript.exe` (Windows-subsystem host — no console window flashes when the task fires) instead of invoking the application binary directly.
1220512192

12193+
### Orphan cleanup after uninstall
12194+
12195+
Users uninstall apps without thinking about background scheduled tasks. Without explicit cleanup, the OS would keep firing schedules pointing to a missing executable forever. Nucleus handles this differently per platform:
12196+
12197+
- **Linux** and **Windows** — the scheduler does *not* register the application binary directly. It writes a tiny wrapper script (`<taskId>.sh` in `nucleus/scheduler//scripts/` on Linux, `<taskId>.vbs` in `%LOCALAPPDATA%\nucleus\scheduler\\scripts\` on Windows) and registers *that* with systemd / Task Scheduler. The wrapper checks whether the application binary still exists before invoking it. If it's gone, the wrapper **self-destructs**: it disables and deletes the systemd `.timer` / `.service` units (Linux) or removes the COM tasks under `\Nucleus\\` (Windows) via the same Schedule.Service API used to create them, deletes the persisted metadata, and finally removes itself. Net result: the next time the OS triggers a task whose app has been uninstalled, the schedule cleans itself up and stops firing.
12198+
- **macOS** — **no automatic cleanup.** Unlike the Linux/Windows wrapper trick, the agent's `ProgramArguments` points directly at the application binary so the entry stays visible under its real name in System Settings → "Allow in the Background". The cost: when the user trashes the .app bundle, the orphaned `.plist` in `~/Library/LaunchAgents/` is **never** reclaimed by macOS, and launchd keeps attempting to spawn the missing binary forever — throttled by `ThrottleInterval` (10 s by default), logging `cannot spawn` to `system.log` on every attempt. SMAppService (macOS 13+) does not eliminate this either, and Apple ships no guidance for "graceful uninstall of a LaunchAgent" — the macOS ecosystem treats orphaned LaunchAgents as a known limitation that an explicit cleanup step has to handle. The mitigation Nucleus offers is **in-app**: call `DesktopTaskScheduler.cancelAll()` from your app's settings ("Disable background tasks") or from any in-app sign-out / reset flow — this unloads the agents and removes the plists cleanly while the binary is still around. If the user does a plain drag-to-trash without that step, the orphan leaks; the leftover plist then has to be removed manually:
12199+
12200+
```bash
12201+
rm ~/Library/LaunchAgents/io.github.kdroidfilter.nucleus..<taskId>.plist
12202+
```
12203+
12204+
The failure mode in the meantime is the well-known throttled-log-spam — not a crash and not a security or correctness issue.
12205+
1220612206
## Testing
1220712207

1220812208
The `scheduler-testing` module provides two levels of test support, inspired by Android's `work-testing`.

docs/llms.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ Everything from the official plugin works unchanged:
739739
- [Launcher (macOS)](https://nucleus.kdroidfilter.com/runtime/launcher-macos/)
740740
- [Launcher (Windows)](https://nucleus.kdroidfilter.com/runtime/launcher-windows/)
741741
- [Launcher (Linux)](https://nucleus.kdroidfilter.com/runtime/launcher-linux/)
742-
- [Media Control (Linux + macOS + Windows)](https://nucleus.kdroidfilter.com/runtime/media-control/)
742+
- [Media Control](https://nucleus.kdroidfilter.com/runtime/media-control/)
743743
- [Dark Mode Detector](https://nucleus.kdroidfilter.com/runtime/darkmode-detector/)
744744
- [System Color](https://nucleus.kdroidfilter.com/runtime/system-color/)
745745
- [System Info](https://nucleus.kdroidfilter.com/runtime/system-info/)

0 commit comments

Comments
 (0)