Honor keepLoaded for services during plugin hot-reload (#9485)
* Honor keepLoaded for services during plugin hot-reload Plugin reload destroyed every service, including omarchy.lock, which drops the ext-session-lock client while Hyprland still holds the lock and surfaces the crashed-lockscreen fallback. * Prove keepLoaded service survival with a fixture service A fresh lock service also reports an empty lastEventAt, so comparing it across the rescan passed whether or not the instance survived. A fixture keepLoaded service whose in-memory marker is set before the rescan and read back after can only pass when the same instance is still mounted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Drop kept services whose plugin no longer declares a service The _syncServices cleanup only asked whether the plugin was still installed and enabled, so a kept service whose plugin dropped its service kind or entry point kept running as a zombie until shell restart. Apply the same eligibility checks used at creation, and hand kept instances the refreshed manifest after a rescan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Cover omarchy.media in keepLoaded expectations; note kept services reload on restart Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
6 files changed
+122
-9
No files matched your search
+27
-4
@@ -329,14 +329,23 @@ ShellRoot {
|
||||
if (!Array.isArray(m.kinds) || m.kinds.indexOf("service") === -1) continue
|
||||
if (!m.entryPoints || !m.entryPoints.service) continue
|
||||
if (!pluginRegistry.isEnabled(id)) continue
|
||||
if (_services[id]) continue
|
||||
if (_services[id]) {
|
||||
// A kept instance outlives the rescan; hand it the fresh manifest.
|
||||
var kept = _services[id]
|
||||
if (kept && "manifest" in kept) kept.manifest = m
|
||||
continue
|
||||
}
|
||||
ensureService(id)
|
||||
}
|
||||
// Drop services for plugins that have been disabled or removed.
|
||||
// Drop services for plugins that have been disabled or removed, or that
|
||||
// no longer declare a service entry point.
|
||||
for (var existingId in _services) {
|
||||
var stillThere = plugins[existingId]
|
||||
var stillService = stillThere && Array.isArray(stillThere.kinds)
|
||||
&& stillThere.kinds.indexOf("service") !== -1
|
||||
&& stillThere.entryPoints && stillThere.entryPoints.service
|
||||
var stillEnabled = stillThere && pluginRegistry.isEnabled(existingId)
|
||||
if (stillThere && stillEnabled) continue
|
||||
if (stillService && stillEnabled) continue
|
||||
var inst = _services[existingId]
|
||||
if (inst && typeof inst.destroy === "function") inst.destroy()
|
||||
var next = ({})
|
||||
@@ -345,12 +354,26 @@ ShellRoot {
|
||||
}
|
||||
}
|
||||
|
||||
function serviceKeepLoaded(pluginId) {
|
||||
var plugins = pluginRegistry && pluginRegistry.installedPlugins
|
||||
var manifest = plugins ? plugins[pluginId] : null
|
||||
return !!(manifest && manifest.keepLoaded === true)
|
||||
}
|
||||
|
||||
// keepLoaded services (lock, idle, polkit) must survive plugin hot-reload.
|
||||
// Destroying omarchy.lock drops the ext-session-lock client while Hyprland
|
||||
// still holds the lock, which surfaces the crashed-lockscreen fallback.
|
||||
function unloadPluginServices() {
|
||||
var next = ({})
|
||||
for (var existingId in _services) {
|
||||
if (serviceKeepLoaded(existingId)) {
|
||||
next[existingId] = _services[existingId]
|
||||
continue
|
||||
}
|
||||
var inst = _services[existingId]
|
||||
if (inst && typeof inst.destroy === "function") inst.destroy()
|
||||
}
|
||||
_services = ({})
|
||||
_services = next
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
||||
Reference in new issue
Block a user