Conversation
…inks Two daemon/plugin robustness fixes (replaces the earlier "sync symlinks on daemon fork" attempt, which had no effect — the wipe happened after it). 1. Stop detached daemons that lost their PID file (utils/daemon/Daemon.py). A daemon is launched via `venv_exec` with `Daemon(daemon_id='<id>')` embedded in the executed code, so the daemon_id stays visible in the process command line. When the PID file is lost (the launcher exited without cleanup, leaving an orphaned daemon), `Daemon.pid` now recovers the PID by scanning for that marker, so status reflects reality instead of a false "stopped". `kill()`/`quit()` reap EVERY process matching the daemon_id (SIGTERM then SIGKILL) — no more `pkill meerschaum` or hunting the id in htop. New helpers: `_find_detached_pids`, `_kill_detached_processes`. 2. Don't remove valid plugin symlinks during sync (plugins/__init__.py). `sync_plugins_symlinks()` removed any symlink whose target wasn't in the CURRENT `PLUGINS_DIR_PATHS`. That path list is process-global and transiently falls back to the host default when `MRSM_PLUGINS_DIR` is momentarily absent (observed across daemon threads / replace_env contexts), so a sync in that window deleted another root's project plugin symlinks from the shared per-root `.internal/plugins` — making a `plugin:`-backed job fail to import. Now only TRULY stale symlinks (target gone) are reaped; valid cross-dir symlinks are left in place. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`replace_env`'s finally cleared `os.environ` entirely (`clear()` + `update(old_environ)`) before restoring it. In a multi-threaded daemon (job target + check-jobs RepeatTimer) a concurrent `sync_plugins_symlinks` could read `MRSM_PLUGINS_DIR` as absent during that blank window, fall back to the host plugins dir, and never create a project's plugin symlinks — so a `plugin:<name>` background job failed to import its plugin. - Restore `os.environ` by diffing instead of clearing it: keys present in `old_environ` are never removed, so `MRSM_PLUGINS_DIR` never momentarily vanishes. - Serialize the process-global env/paths swap under a new `_replace_env_lock` (held only around the mutation, not across `yield`). Complements the dev1 only-reap-stale symlink fix (which stopped the wipe class); this stops the never-created class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`unload_plugins(remove_symlinks=True)` deleted a plugin's symlink from the per-root `.internal/plugins` directory unconditionally. That directory is SHARED by every process operating on the root, including a `plugin:<name>` background job started moments earlier. `mrsm compose start jobs` loads the project plugins, starts the job daemon (which needs the symlink), then unloads the plugins it loaded — and the unload removed the symlink out from under the running daemon, so its plugin import failed with "Plugin '<name>' cannot be found". This was the never-created/never-persisted symlink class behind the `compose start jobs` failures (`compose up` happened to dodge it). Apply the same only-reap-stale invariant already used in `sync_plugins_symlinks`: only remove a symlink whose target no longer exists. In-memory unloading (popping `sys.modules`) is process-local and is all that unloading needs; symlink lifecycle is owned by `sync_plugins_symlinks`. Verified against a throwaway compose project with a `plugin:`-backed job: `compose start jobs` (in-process AND isolation: subprocess), stop+start persistence, and `compose up` all keep the symlink and import the plugin; genuinely stale symlinks (target gone) are still cleaned. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.