Fixing precompilation hangs due to open tasks or IO
في جوليا 1.10 أو أعلى، قد ترى الرسالة التالية:
قد يتكرر هذا. إذا استمر في التكرار دون أي تلميحات بأنه ستحل المشكلة من تلقاء نفسها، فقد تواجه "توقف ما قبل التجميع" يتطلب الإصلاح. حتى لو كان مؤقتًا، قد تفضل حله حتى لا ينزعج المستخدمون من هذه التحذيرات. هذه الصفحة ترشدك خلال كيفية تحليل وإصلاح مثل هذه المشكلات.
إذا اتبعت النصيحة وضغطت على 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
تحتوي هذه الرسالة على نقطتين رئيسيتين:
- يحدث التعليق أثناء ما قبل التجميع لـ
Test1
، وهو اعتماد لـTest2
(الحزمة التي كنا نحاول تحميلها باستخدامusing Test2
) - خلال مرحلة ما قبل التجميع لـ
Test1
، أنشأت جوليا كائنTimer
(استخدم?Timer
إذا كنت غير مألوف بـ Timers) والذي لا يزال مفتوحًا؛ حتى يتم إغلاقه، ستظل العملية متوقفة.
إذا كانت هذه تلميحًا كافيًا لك لتكتشف كيف يتم إنشاء timer = Timer(args...)
، فإن إحدى الحلول الجيدة هي إضافة wait(timer)
إذا كان timer
ينتهي في النهاية من تلقاء نفسه، أو close(timer)
إذا كنت بحاجة إلى إغلاقه بالقوة، قبل النهاية النهائية للوحدة.
ومع ذلك، هناك حالات قد لا تكون بهذه السهولة. عادةً ما تكون أفضل خيار هو البدء بتحديد ما إذا كان التوقف ناتجًا عن الكود في Test1 أو ما إذا كان ناتجًا عن أحد تبعيات Test1:
- الخيار 1:
Pkg.add("Aqua")
واستخدمAqua.test_persistent_tasks
. يجب أن يساعدك هذا في تحديد الحزمة التي تسبب المشكلة، بعد ذلك يجب اتباع التعليمات below. إذا لزم الأمر، يمكنك إنشاءPkgId
كـBase.PkgId(UUID("..."), "Test1")
، حيث يأتي...
من إدخالuuid
فيTest1/Project.toml
. - الخيار 2: تشخيص مصدر التوقف يدويًا.
لتشخيص يدوي:
Pkg.develop("Test1")
- Comment out all the code
include
d or defined inTest1
, except theusing/import
statements. - حاول
using Test2
(أو حتىusing Test1
على افتراض أن ذلك يتسبب في تعليق أيضًا) مرة أخرى
الآن نصل إلى مفترق طرق: إما
- يستمر التعليق، مما يدل على أنه due to one of your dependencies
- تختفي التعليق، مما يدل على أنه due to something in your code.
Diagnosing and fixing hangs due to a package dependency
استخدم بحث ثنائي لتحديد الاعتماد المسبب للمشكلة: ابدأ بالتعليق على نصف اعتماداتك، ثم عندما تعزل النصف المسؤول، علق على نصف ذلك النصف، وهكذا. (لا تحتاج إلى إزالتها من المشروع، فقط علق على عبارات using
/import
.)
بمجرد تحديدك لمشتبه به (سنطلق عليه هنا ThePackageYouThinkIsCausingTheProblem
)، حاول أولاً تجميع تلك الحزمة مسبقًا. إذا توقفت أيضًا أثناء التجميع المسبق، استمر في تتبع المشكلة إلى الوراء.
ومع ذلك، من المرجح أن ThePackageYouThinkIsCausingTheProblem
ستقوم بالتجميع المسبق بشكل جيد. وهذا يشير إلى أنه في الدالة ThePackageYouThinkIsCausingTheProblem.__init__
، التي لا تعمل أثناء التجميع المسبق لـ ThePackageYouThinkIsCausingTheProblem
ولكن تفعل في أي حزمة تقوم بتحميل ThePackageYouThinkIsCausingTheProblem
. لاختبار هذه النظرية، قم بإعداد مثال عمل بسيط (MWE)، شيء مثل
(@v1.10) pkg> generate MWE
Generating project MWE:
MWE\Project.toml
MWE\src\MWE.jl
أين يوجد كود المصدر لـ MWE.jl
module MWE
using ThePackageYouThinkIsCausingTheProblem
end
وقد أضفت ThePackageYouThinkIsCausingTheProblem
إلى تبعيات MWE.
إذا كان هذا المثال البسيط يعيد إنتاج التوقف، فقد وجدت الجاني: ThePackageYouThinkIsCausingTheProblem.__init__
يجب أن يكون قد أنشأ كائن Timer
. إذا كان من الممكن إغلاق كائن المؤقت بأمان، فهذه خيار جيد. خلاف ذلك، فإن الحل الأكثر شيوعًا هو تجنب إنشاء المؤقت أثناء أي حزمة يتم تجميعها مسبقًا: أضف
ccall(:jl_generating_output, Cint, ()) == 1 && return nothing
كالسطر الأول من ThePackageYouThinkIsCausingTheProblem.__init__
، وسيتجنب القيام بأي تهيئة في أي عملية جوليا الغرض منها تجميع الحزم مسبقًا.
Fixing package code to avoid hangs
ابحث في حزمة الخاص بك عن كلمات توحي (هنا مثل "مؤقت") وانظر إذا كنت تستطيع تحديد مكان المشكلة التي يتم إنشاؤها. لاحظ أن تعريف الطريقة مثل
maketimer() = Timer(timer -> println("hi"), 0; interval=1)
ليس مشكلة في حد ذاته: يمكن أن يسبب هذه المشكلة فقط إذا تم استدعاء maketimer
أثناء تعريف الوحدة. قد يحدث هذا من عبارة على المستوى الأعلى مثل
const GLOBAL_TIMER = maketimer()
أو قد يحدث بشكل محتمل في precompile workload.
إذا كنت تواجه صعوبة في تحديد الخطوط المسببة، ففكر في إجراء بحث ثنائي: قم بالتعليق على أقسام من حزمةك (أو استخدم include
لاستبعاد ملفات كاملة) حتى تقلل نطاق المشكلة.