执行外部程序后修改$*SCHEDULER引发异常的技术问询
问题描述
以下是示例代码:
#!/bin/env raku run 'raku', '-e', 'say "ok"'; exit 0; my $*SCHEDULER = ThreadPoolScheduler.new(max_threads => 128);
Linux系统下输出如下:
ok Unhandled exception in code scheduled on thread 4 No such method 'cue' for invocant of type 'Any'
Windows系统下输出如下:
Unhandled exception in code scheduled on thread 4 No such method 'cue' for invocant of type 'Any' in method throw at 'SETTING::'src/core.c/Exception.pm6 line 65 in method schedule_thens at 'SETTING::'src/core.c/Promise.pm6 line 167 in method keep at 'SETTING::'src/core.c/Promise.pm6 line 127 in method keep at 'SETTING::'src/core.c/Promise.pm6 line 83 in block at 'SETTING::'src/core.c/Proc/Async.pm6 line 390 in block at 'SETTING::'src/core.c/ThreadPoolScheduler.pm6 line 263 in method run-one at 'SETTING::'src/core.c/ThreadPoolScheduler.pm6 line 244 in block at 'SETTING::'src/core.c/ThreadPoolScheduler.pm6 line 308 in sub THREAD-ENTRY at 'SETTING::'src/core.c/Thread.pm6 line 69
有时会在错误前打印ok,有时在错误后,有时不打印,无固定规律。
技术解答
1. 该情况是否属于Bug?
这是Raku核心库的Bug。主线程提前退出后,异步任务的后续处理逻辑没有正确处理调度器未初始化或已失效的情况,导致抛出未捕获的异常,属于核心实现中进程退出与异步任务生命周期同步的疏漏。
2. 该错误的含义是什么?出现的原因是什么?
- 错误含义:代码尝试调用一个
Any类型对象的cue方法,但Any类并未定义此方法,因此触发异常。 - 出现原因:
run函数本质是异步启动外部进程(返回Proc::Async对象),主线程执行exit 0时,监控该异步进程的后台线程仍在运行。而$*SCHEDULER的赋值语句写在exit之后,根本不会被执行,后台线程中访问$*SCHEDULER时得到的是默认的Any类型值,调用其cue方法自然会报错。
3. 为何执行exit 0后仍会出现该问题?
exit只会终止主线程,但Raku不会立刻强制终止所有后台异步线程。主线程退出后,进程并不会马上结束,后台线程还会继续运行一段时间。当这些线程处理异步进程结束后的Promise回调时,需要使用调度器来安排任务,此时因为$*SCHEDULER未被初始化,就会触发异常并输出错误信息。而ok的输出顺序无规律,是因为主线程的输出和后台线程的异常输出之间没有同步机制,属于竞态条件导致的结果。
内容的提问来源于stack exchange,提问作者fingolfin
相关产品推荐
相关产品推荐

