总览:https://github.com/agentic-ai-java/argi/issues/180 ## 代码依据 https://github.com/agentic-ai-java/argi/blob/f45b2cf7a2fb301744fa61ef423795f6d30b65da/argi-graph-core/src/main/java/io/github/agentic/ai/graph/scheduling/DefaultScheduledAgentManager.java#L78 ## 问题与验收 registerTask 在获取写锁前检查 shutdown,之后才加锁写入 activeTasks;shutdown 在同一写锁下清空任务并关闭 scheduler。可能出现注册线程先检查通过、shutdown 完成、注册线程再向已关闭 manager 写入的交错。 ## 范围与验收 - [ ] 构造可控交错验证 shutdown 完成后无新任务进入 activeTasks;不能只重复跑概率性压力测试。 - [ ] 在同一同步边界内完成运行状态检查与注册;关闭开始后明确拒绝或按已定义准入规则处理。 - [ ] 并发注册/注销/shutdown 保持幂等,无遗留记录、死锁或持锁回调造成的不可控阻塞。 - [ ] 验证 close 期间任务 stop 回调和 manager 注销的重入路径,不能简单换锁而引入死锁。 - [ ] 保持自定义 ScheduledAgentManager 契约和既有任务清理,明确拒绝异常及消费者影响。 - [ ] 与 OPT-23/24 协调局部生命周期修复;不重复 #124 持久化执行或 Extensions #16 调度去重。 现有 singleton 的可重用/重建策略仅作相关约束记录,本单不扩展为全局容器重写。 ## 验证与兼容约束 Core 基线 f45b2cf7a2fb301744fa61ef423795f6d30b65da。当前为静态代码分析,尚未运行本单针对性复现。先补有意义的行为测试,优先局部修复;公共 API/输出/调度语义变化需说明收益、影响、兼容替代、迁移成本及目标版本。修复不等待 Agent/Workflow/Loop 全局重构。 ## 关联任务 - https://github.com/agentic-ai-java/argi/issues/214 - https://github.com/agentic-ai-java/argi/issues/215
Activity
konlue commentedon Nov 14, 2026
您好,我想认领 #216。
方案(根因定位在
DefaultScheduledAgentManager.registerTask,实际模块为 argi-orchestration/argi-workflow-graph-core,issue 链接的 argi-graph-core 路径是旧布局)registerTask的 shutdown 检查在写锁之外,检查通过后线程可被抢占;shutdown()在同一写锁内停全部任务、清空activeTasks、关 scheduler 并置标志后,注册线程再拿锁插入——任务滞留在已关闭 manager 里,永不停止且getActiveTaskCount()不归零。shutdown()置标志就在这同一把写锁内,两者构成原子互斥。不换锁类型——shutdown 持锁回调task.stop()会重入unregisterTask的写锁,可重入性必须保持。ScheduledAgentManager.registerTaskjavadoc 补@throws IllegalStateException——关闭开始后的注册(含与进行中 shutdown 交错的注册)必须被拒绝,不留滞留记录。DefaultScheduledAgentManager增加包私有构造器注入 TaskScheduler(eager 单例不可复活,真实 scheduler 无法驱动确定性交错测试)。测试(新
ScheduledAgentManagerShutdownMutexTest,确定性交错、非概率压测)activeTasks:shutdown 线程持写锁停在 stop 回调(STOPPED 监听器 latch 阻塞),注册线程经task.getName()可控缝隙在旧代码下确认通过锁外检查后阻塞在锁上;放行 shutdown 完成后,旧代码滞留注册(修复前红),新代码被锁内复查拒绝、计数归零。