mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
Part 1 加载分派骨架(迁移可逐插件推进、随时回退的前提):
- dynamic.go: 新增 binEntry/skillEntry 常量 + entryKind 枚举 + classifyEntry/detectEntryKind
manifest entry 优先级最高(改回 plugin.so 即回退 cabi);无 manifest 时按目录探测,.bin 优先
- registry.go: tryDynamic 按 entry 分派 proc/cabi 双通道;
entry 声明 .bin 但二进制缺失时报明确错误,不静默回退(否则'已迁移插件跑回旧通道'极难排查)
- registry.go: pluginEntryHash 候选顺序与 detectEntryKind 对齐(.bin 优先),
否则增量重载会用错文件算 hash
- dynamic_proc_{unix,windows}.go: tryLoadProc 桩位(权限/类型校验已实现,进程管理属 Part 2)
Part 4 共享内存数据面(迁移评估 §3.3/§3.4/§3.7,最关键一环):
- proc/shm.go: 段布局(Header + ShmStageCtx 描述符数组 + append-only arena)
相对偏移设计——各进程 mmap 到不同虚拟地址仍能正确解引用
arena 用尽显式报错而非静默截断(§4.4 风险登记);Compact() 回收 append-only 垃圾
- proc/shmcodec.go: StageContext 16 字段跨进程编解码
字段级描述符消除 lost update:只改 FinalText 的插件不触碰 ToolResults 描述符
WriteDirty 只写脏字段——只读插件零写入,不可能覆盖他人改写
Snapshot 存序列化字符串(切片共享底层数组的坑,C ABI 侧修 11.3 时已踩过)
Extra 4 键提升为具名字段;Response 用标志位表达 nil vs 空串
- proc/lock.go: 锁仲裁回归内核(§3.7 已裁定,零 cgo)
ForceRelease 实现实验 9 的崩溃自愈——排除 robust pthread_mutex 必要性
重复加锁显式拒绝(否则死锁 30s);等待超时有补偿 goroutine 防锁泄漏
验证:
- proc 包 16 项测试全绿(含 -race):全字段往返/只读零写回/原地改切片识别/
现网 sanitizer+weather 场景/5插件×40轮并发零丢失/arena 耗尽报错/压实不破坏字段/
锁互斥·串扰拒绝·崩溃自愈·临界区串行化
- entry 分派 9 项测试全绿;go build ./... exit 0;接口冻结 git diff sdk/ 为空
44 lines
1.6 KiB
Go
44 lines
1.6 KiB
Go
//go:build linux || darwin
|
||
|
||
package plugin
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
sdk "gitcode.com/JianFeeeee/HomeAgent/internal/sdk"
|
||
)
|
||
|
||
// tryLoadProc 加载子进程插件(plugin.bin)——外部插件多进程化的加载入口。
|
||
//
|
||
// 设计依据:docs/zh/架构迁移评估.md §3(stdio JSON-RPC 控制面 + shm 数据面 + eventfd 通知面)
|
||
// 实施计划:docs/zh/plugin-migration-plan.md Part 2
|
||
//
|
||
// 当前状态:**分派桩位**。共享内存数据面与锁仲裁已在 internal/plugin/proc/ 落地
|
||
// 并通过 16 项测试(含 -race),进程管理与 RPC 编解码为 Part 2 内容。
|
||
//
|
||
// 返回 nil,nil 表示目录中没有 plugin.bin(交由后续探测通道)。
|
||
// 找到二进制但通道未就绪时返回明确错误——不静默回退到 cabi,
|
||
// 否则"已迁移插件跑回旧通道"极难排查。
|
||
func tryLoadProc(dir, name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||
binPath := filepath.Join(dir, binEntry)
|
||
st, err := os.Stat(binPath)
|
||
if err != nil {
|
||
if os.IsNotExist(err) {
|
||
return nil, nil
|
||
}
|
||
return nil, fmt.Errorf("proc plugin %s: 检查 %s: %w", name, binEntry, err)
|
||
}
|
||
if st.IsDir() {
|
||
return nil, fmt.Errorf("proc plugin %s: %s 是目录,不是可执行文件", name, binEntry)
|
||
}
|
||
if st.Mode()&0o111 == 0 {
|
||
return nil, fmt.Errorf("proc plugin %s: %s 缺少可执行权限(chmod +x)", name, binEntry)
|
||
}
|
||
|
||
return nil, fmt.Errorf("proc plugin %s: 子进程通道尚未实现(Part 2)——"+
|
||
"共享内存数据面已就绪(internal/plugin/proc),"+
|
||
"如需运行请把 plugin.json 的 entry 改回 %s 走 C ABI 通道", name, soEntry)
|
||
}
|