AnyMath 文档

修复由于打开任务或IO而挂起的预编译

在Julia1.10或更高版本上,您可能会看到以下消息:

precompilation hang

这可能会重复。 如果它继续重复而没有提示它会自行解决,那么您可能会有一个需要修复的"预编译挂起"。 即使它是暂时的,您可能更愿意解决它,以便用户不会受到此警告的困扰。 本页将引导您了解如何分析和解决此类问题。

如果你听从建议,打 Ctrl-C,你可能会看到

^C Interrupted: Exiting precompilation...

  1 dependency had warnings during precompilation:
┌ Test1 [ac89d554-e2ba-40bc-bc5c-de68b658c982]
│  [pid 2745] waiting for IO to finish:
│   Handle type        uv_handle_t->data
│   timer              0x55580decd1e0->0x7f94c3a4c340

这条信息传达了两个关键信息:

*挂起是在预编译期间发生的 测试1,一个依赖 测试2 (我们试图装载的包裹 使用Test2) *在预编译期间 测试1,朱莉娅创造了一个 定时器 对象(使用 ?定时器 如果你不熟悉计时器),它仍然是开放的;直到关闭,进程被挂起

如果这是一个足够的提示,让你弄清楚如何 定时器=定时器(args。..) 正在创建,一个很好的解决方案是添加 等待(计时器) 如果 定时器 最终自行完成,或 关闭(计时器) 如果你需要强制关闭它,在决赛之前 结束 的模块。

但是,有些情况可能不是那么简单。 通常最好的选择是首先确定挂起是由于Test1中的代码还是由于Test1的依赖项之一:

*备选案文1: Pkg。添加("水") 和使用https://juliatesting.github.io/Aqua.jl/dev/#Aqua.test_persistent_tasks-Tuple{Base.PkgId}[水族。test_persistent_tasks]. 这应该可以帮助您确定导致问题的软件包,之后说明 应遵循。 如果需要,您可以创建一个 PkgId,PkgId 作为 基地。PkgId(UUID("。.."),"Test1"),在哪里 ... 来自 uuid 进入 Test1/项目。汤姆尔. *选项2:手动诊断挂起的来源。

手动诊断:

  1. Pkg。开发("Test1")

  2. 注释掉所有的代码 包括d或定义于 测试1,_except_的 使用/导入 发言。

  3. 试试 使用Test2 (甚至 使用Test1 假设也挂起)再次

现在我们到达了一个岔路口:要么

*挂起仍然存在,表明它是 由于您的一个依赖项 *挂起消失,表明它是 由于您的代码中的某些内容

诊断和修复因包依赖而挂起的问题

使用二进制搜索来识别有问题的依赖关系:从注释掉一半的依赖关系开始,然后当你隔离哪一半负责时,注释掉那一半的一半,等等。 (您不必将它们从项目中删除,只需注释掉 使用/进口 发言。)

一旦你确定了一个嫌疑犯(在这里我们称之为 你的想法,你的想法),首先尝试预编译该包。 如果它在预编译期间也挂起,请继续向后追逐问题。

然而,最有可能的 你的想法,你的想法 将预编译罚款。 这表明它在函数中 你的想法是关于问题的。__init__,在预编译期间不运行 你的想法,你的想法 但是_does_在任何加载的包中 你的想法,你的想法. 为了测试这个理论,建立一个最小工作示例(MWE),类似于

(@v1.10) pkg> generate MWE
  Generating  project MWE:
    MWE\Project.toml
    MWE\src\MWE.jl

其中的源代码 MWE。jl

module MWE
using ThePackageYouThinkIsCausingTheProblem
end

你还补充道 你的想法,你的想法 到MWE的依赖关系。

如果那个MWE重现了绞刑,你就找到了罪魁祸首: 你的想法是关于问题的。__init__ 必须创建 定时器 对象。 如果timer对象可以安全 接近/接近d,这是一个很好的选择。 否则,最常见的解决方案是避免在_any_包正在预编译时创建计时器:添加

ccall(:jl_generating_output, Cint, ()) == 1 && return nothing

作为第一行 你的想法是关于问题的。__init__,并且它将避免在任何Julia进程中进行任何初始化,其目的是预编译包。

修复包代码以避免挂起

在你的包中搜索暗示性的单词(这里像"计时器"),看看你是否能确定问题的产生位置。 请注意,类似于_definition_的方法

maketimer() = Timer(timer -> println("hi"), 0; interval=1)

本身没有问题:只有在以下情况下才会导致这个问题 使蒂默 在定义模块时被调用。 这可能发生在顶级语句中,例如

const GLOBAL_TIMER = maketimer()

或者它可能发生在一个https://github.com/JuliaLang/PrecompileTools.jl[预编译工作负载]。

如果你很难确定原因行,那么考虑做一个二进制搜索:注释掉你的包的部分(或者 包括 行以省略整个文件),直到您减少了范围内的问题。