mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-04 00:03:59 +00:00
plugin: 卸载/重载后 dlclose 动态库句柄(cabiPlugin.Close),修复同路径 dlopen 复用旧句柄导致插件更新不生效
This commit is contained in:
@ -51,6 +51,13 @@ func (p *cabiPlugin) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close 卸载动态库(dlclose)。卸载/重载后必须调用,否则同一路径的 dlopen
|
||||||
|
// 会复用旧句柄(Linux dlopen 语义),新版本的 plugin.so 不会生效。
|
||||||
|
func (p *cabiPlugin) Close() error {
|
||||||
|
p.handle.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func tryLoadSO(dir, name string, config map[string]interface{}) (sdk.Plugin, error) {
|
func tryLoadSO(dir, name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||||||
soPath := filepath.Join(dir, soEntry)
|
soPath := filepath.Join(dir, soEntry)
|
||||||
if _, err := os.Stat(soPath); os.IsNotExist(err) {
|
if _, err := os.Stat(soPath); os.IsNotExist(err) {
|
||||||
|
|||||||
@ -424,6 +424,7 @@ func (r *Registry) ReloadOne(name string) error {
|
|||||||
plgDir := filepath.Join(r.plgDir, name)
|
plgDir := filepath.Join(r.plgDir, name)
|
||||||
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
|
var removed sdk.Plugin
|
||||||
if p, ok := r.plugins[name]; ok {
|
if p, ok := r.plugins[name]; ok {
|
||||||
r.runStopHandlers(name)
|
r.runStopHandlers(name)
|
||||||
if err := p.Stop(); err != nil {
|
if err := p.Stop(); err != nil {
|
||||||
@ -437,9 +438,12 @@ func (r *Registry) ReloadOne(name string) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
removed = p
|
||||||
}
|
}
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
|
|
||||||
|
r.closeDynamic(removed)
|
||||||
|
|
||||||
ok := r.loadOne(plgDir, name)
|
ok := r.loadOne(plgDir, name)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("reload plugin %s failed", name)
|
return fmt.Errorf("reload plugin %s failed", name)
|
||||||
@ -448,6 +452,20 @@ func (r *Registry) ReloadOne(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// closeDynamic 释放动态加载插件的共享库句柄(dlclose)。
|
||||||
|
// Linux dlopen 对同一路径返回已加载的旧句柄,若不释放,插件二进制更新后
|
||||||
|
// 重载/卸载仍会执行旧代码。Go plugin.Open 路径(dynamicPlugin)不可卸载,跳过。
|
||||||
|
func (r *Registry) closeDynamic(p sdk.Plugin) {
|
||||||
|
if p == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c, ok := p.(interface{ Close() error }); ok {
|
||||||
|
if err := c.Close(); err != nil {
|
||||||
|
log.Printf("[plugin] close dynamic %s: %v", p.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Registry) List() []string {
|
func (r *Registry) List() []string {
|
||||||
r.mu.RLock()
|
r.mu.RLock()
|
||||||
defer r.mu.RUnlock()
|
defer r.mu.RUnlock()
|
||||||
@ -588,10 +606,11 @@ func (r *Registry) DisablePlugin(name, by string) error {
|
|||||||
func (r *Registry) EnablePlugin(name string) error { return r.Enable(name) }
|
func (r *Registry) EnablePlugin(name string) error { return r.Enable(name) }
|
||||||
|
|
||||||
// RemovePlugin 卸载插件:先停止(stop handlers + Stop),再执行插件注册的 onRemove
|
// RemovePlugin 卸载插件:先停止(stop handlers + Stop),再执行插件注册的 onRemove
|
||||||
// 回调(删除专用,重载不触发),最后从注册表移除并清理禁用/工具注册。
|
// 回调(删除专用,重载不触发),最后从注册表移除并清理禁用/工具注册/配置。
|
||||||
// 插件目录的物理删除由调用方(pluginmgr)负责。
|
// 插件目录的物理删除由调用方(pluginmgr)负责。
|
||||||
func (r *Registry) RemovePlugin(name string) error {
|
func (r *Registry) RemovePlugin(name string) error {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
|
var removed sdk.Plugin
|
||||||
p, ok := r.plugins[name]
|
p, ok := r.plugins[name]
|
||||||
if ok {
|
if ok {
|
||||||
r.runStopHandlers(name)
|
r.runStopHandlers(name)
|
||||||
@ -606,6 +625,7 @@ func (r *Registry) RemovePlugin(name string) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
removed = p
|
||||||
}
|
}
|
||||||
r.runOnRemoveHandlers(name)
|
r.runOnRemoveHandlers(name)
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
@ -617,6 +637,7 @@ func (r *Registry) RemovePlugin(name string) error {
|
|||||||
r.cfgReg.RemoveDisabledPlugin(name)
|
r.cfgReg.RemoveDisabledPlugin(name)
|
||||||
r.cfgReg.RemovePlugin(name)
|
r.cfgReg.RemovePlugin(name)
|
||||||
}
|
}
|
||||||
|
r.closeDynamic(removed)
|
||||||
log.Printf("[plugin] removed: %s", name)
|
log.Printf("[plugin] removed: %s", name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user