حين يتعطّل تطبيق التحكّم بكاميرا صناعيّة فجأةً بعد شهر (الجزء الأوّل) - كيفيّة العثور على handle leak وتصميم السجلّات للتشغيل طويل الأمد
· 小村 豪 · تطوير Windows, تصحيح الأخطاء, الكاميرا الصناعيّة, handle leak, تصميم السجلّات
حين يتعطّل تطبيق Windows فجأةً بعد تشغيله لفترة طويلة فقط، فإنّ أوّل ما يخطر بالبال هو الشكّ في تسريب الذاكرة.
لكن في الممارسة العمليّة، يكون الجاني الرئيسيّ أحياناً handle leak، وما يظهر أخيراً بعد أسابيع ليس سوى العطل الثانويّ.
الحالة هنا هي تطبيق Windows كان يتحكّم بكاميرا صناعيّة وتعطّل فجأةً بعد حوالي شهر من التشغيل المتواصل. بعد تضييق نطاق التحقيق، تبيّن أنّ السبب الحقيقيّ هو handle leak على مسار فشل في منطق إعادة اتّصال الكاميرا.
في هذا الجزء الأوّل، سأنظّم ما يعنيه handle leak، وكيف تمّ تضييق نطاق هذه الحالة، وما هي السجلّات التي تستحقّ الإضافة لاحقاً لمنع نفس الألم في التحقيق.
أمّا الجزء الثاني، حين يتعطّل تطبيق التحكّم بكاميرا صناعيّة فجأةً بعد شهر (الجزء الثاني) - ما هو Application Verifier وكيف نبني بنية اختبار لمسارات الفشل، فيتناول جانب اختبار مسارات الفشل.
تمّ تعميم بعض الأسماء الخاصّة وعدد قليل من عناصر السجلّ، لكنّ التفكير الأساسيّ ينطبق بشكل واسع جدّاً على تطبيقات التحكّم بالأجهزة المعتمدة على Windows.
المحتويات
- النسخة المختصرة
- ما يعنيه handle leak هنا
- دراسة حالة: تطبيق التحكّم بالكاميرا الصناعيّة الذي تعطّل بعد شهر
- كيف ضيّقنا نطاق التحقيق
- ما هي السجلّات اللازمة لمنع تكرار الحادث
- دليل قواعد عامّة تقريبيّة
- الخلاصة
- المراجع
1. النسخة المختصرة
- في تطبيقات التحكّم التي تفشل فقط بعد التشغيل طويل الأمد، انظر دائماً إلى
Handle Countبالإضافة إلىPrivate Bytes - تميل عمليّات handle leak إلى الاختباء في مسارات timeout / reconnect / فشل جزئيّ / early return بدلاً من المسار الطبيعيّ
- السطر الذي يتعطّل فيه التطبيق أخيراً ليس في الغالب هو السطر الذي تسرّب منه المورد أصلاً
- أهمّ السجلّات هي سياق operation / session، و
Handle Countعلى مستوى العمليّة، وتماثل فتح / إغلاق الموارد، وتفاصيل أخطاء Win32 / HRESULT / SDK - بدلاً من انتظار شهر آخر لإعادة الإنتاج، اختصر المسار بضرب سيناريوهات الاتّصال / قطع الاتّصال / إعادة الاتّصال / الفشل في حلقة
- Application Verifier، الذي نناقشه في الجزء الثاني، فعّال جدّاً، لكنّ سجلّاتك الخاصّة التي تكشف تماثل دورة حياة الموارد هي الأساس
باختصار، الخطوة الصحيحة الأولى في هذا النوع من الحالات ليست التحديق في “تعطّل بعد فترة طويلة”.
الخطوة الصحيحة هي جعل نموّ الموارد وسلوك مسار الفشل قابلاً للمراقبة.
تظهر عمليّات handle leak غالباً بوجه عطل ثانويّ لاحق.
إذا قرأت الاستثناء النهائيّ فقط، فمن السهل جدّاً أن تسير في الاتّجاه الخاطئ.
2. ما يعنيه handle leak هنا
2.1. ما يعنيه “handle” في هذا السياق
هنا، يعني handle معرّفاً على مستوى عمليّة Windows يُستخدم للإشارة إلى الموارد التي يديرها نظام التشغيل.
الأمثلة النموذجيّة تشمل:
| الفئة | الأمثلة |
|---|---|
| kernel objects | event، mutex، semaphore، thread، process، waitable timer |
| الموارد المتعلّقة بـ I/O | file، pipe، socket، فتح الأجهزة |
| شائعة بشكل خاصّ في تطبيقات التحكّم بالأجهزة | events داخليّة لـ SDK، كائنات تسجيل callback، handles مرتبطة بـ thread الالتقاط |
ما يسبّب المشاكل غالباً في تطبيقات التحكّم هو إنشاء مورد مؤقّتاً لعمليّة معيّنة ونسيان إغلاقه على مسار فشل في المنتصف.
على سبيل المثال:
- إنشاء event واحد في كلّ مرّة تبدأ فيها إعادة الاتّصال
- فشل تسجيل callback أو بدء الالتقاط جزئيّاً في المنتصف
- المسار الناجح يغلقه، لكنّ مسار الفشل لا يفعل
- الاختبارات القصيرة تشغّل في معظمها المسار الناجح، لذا يُفوَّت التسريب
هذا النوع من الأخطاء يختبئ بشكل طبيعيّ جدّاً في كلّ من مراجعة الكود والتشغيل الفعليّ.
2.2. لماذا يظهر غالباً بعد التشغيل طويل الأمد فقط
handle leak لا يفشل بالضرورة بشكل مذهل من الحدوث الأوّل.
النمط الخطر عادةً هو ميل صغير جدّاً: مورد واحد يتسرّب لكلّ فشل.
flowchart LR
A["Normal operation"] --> B["Occasional timeout / reconnect"]
B --> C["Failure path creates an event handle"]
C --> D["CloseHandle is not called"]
D --> E["Handle Count rises slightly"]
E --> F["The pattern repeats hundreds or thousands of times"]
F --> G["Later CreateEvent / SDK open starts failing"]
G --> H["Secondary crash or stop"]
إذا تسرّب من إعادة اتّصال واحدة handle واحد فقط، فقد لا يحدث شيء لأيّام.
لكن في تطبيق تحكّم يعمل 24/7، تتكرّر مراراً وتكراراً حواف timeout وإعادة التهيئة وإعادة الاتّصال.
هكذا يمكن للتسريب أن يطفو على السطح بعد أسابيع فقط.
ما يهمّ هو أنّ handle leak نفسه قد لا يكون السطر الفعليّ للتعطّل النهائيّ.
الأشكال النموذجيّة للفشل اللاحق تشمل:
- استدعاءات API التي تنشئ event / file / thread جديداً تبدأ في الفشل
- يفشل SDK في تهيئة الموارد الداخليّة ويعيد فقط رمز فشل عامّاً
- مسار الخطأ رفيع، والكود اللاحق يتعثّر على
nullأو handle غير صالح - يزداد timeout حتّى يقتل التطبيقَ watchdog أو مسار تحكّم على مستوى أعلى
لذا فإنّ نقطة التعطّل النهائيّة غالباً ما تكون فقط الضحيّة الأخيرة، وليست الجاني الأوّل.
2.3. كيف يختلف عن تسريب الذاكرة
أعطال التشغيل طويل الأمد تجعل الناس يشكّون في تسريبات الذاكرة أوّلاً، وهذا أمر طبيعيّ.
لكن غالباً ما ينبغي التحقيق في عمليّات handle leak على محور مختلف.
| وجهة النظر | تسريب الذاكرة | handle leak |
|---|---|---|
| أوّل مقياس يجب مراقبته | Private Bytes، Commit، Working Set |
Handle Count |
| العَرَض النموذجيّ | ضغط الذاكرة، paging، تباطؤ، OOM | فشل Create* / Open* / تهيئة SDK، أعطال ثانويّة |
| أين تميل إلى الاختباء | المراجع المحتجزة، الـ caches، نسيان التحرير | عدم تماثل بين create/open وclose/dispose |
| الاتّجاه النموذجيّ | تنمو الذاكرة باطّراد | يرتفع Handle Count ولا يعود |
لذلك عند التعامل مع أعطال التشغيل طويل الأمد، فإنّ النظر إلى الذاكرة فقط غالباً ما يشبه القيادة بعين واحدة مغلقة.
كحدّ أدنى، ينبغي فحص Handle Count وThread Count معاً.
3. دراسة حالة: تطبيق التحكّم بالكاميرا الصناعيّة الذي تعطّل بعد شهر
3.1. كيف بدت الأعراض
كانت الأعراض الظاهريّة بسيطة:
- تطبيق Windows يتحكّم بكاميرا صناعيّة يعمل 24/7
- في الظروف العاديّة يعمل بشكل جيّد
- بعد حوالي شهر، يتعطّل فجأةً في يوم ما
- بعد إعادة التشغيل، يعمل مرّة أخرى لفترة
المشكلة الأولى ببساطة هي أنّ الزمن حتّى الفشل طويل جدّاً.
انتظار شهر لكلّ دورة إعادة إنتاج أمر قاسٍ كاستراتيجيّة تحقيق.
ما جعله أكثر إزعاجاً هو أنّ موقع التعطّل لم يكن متطابقاً تماماً في كلّ مرّة.
أحياناً يحدث مباشرةً بعد بدء إعادة الاتّصال، وأحياناً عند بدء الالتقاط، وأحياناً بعد فشل استدعاء SDK.
بهذا المظهر، تبدو كلّ هذه الأمور معقولةً في البداية:
- عدم استقرار في SDK الكاميرا
- أعطال مؤقّتة في الجهاز أو الاتّصالات
- تسريب ذاكرة
- بعض السباقات (race) المتعلّقة بالـ threads
- فشل تهيئة لم يصل إلى السجلّات قطّ
بعبارة أخرى، كان هناك ببساطة عدد كبير جدّاً من الأمور المشبوهة بشكل غامض.
3.2. أوّل المقاييس التي نظرنا إليها
لذا كانت الخطوة الأولى هي النظر إلى كيفيّة نموّ الموارد على مستوى العمليّة.
في هذه الحالة، أشارت الملاحظات تقريباً إلى هذا الاتّجاه:
| المقياس | الاتّجاه الملاحَظ | القراءة |
|---|---|---|
Handle Count |
ارتفع قليلاً بعد إعادات الاتّصال أو timeouts ولم يعد | اشتبه في handle leak |
Private Bytes |
تحرّك صعوداً وهبوطاً، لكنّه لم يُظهر ميلاً رتيباً قويّاً | قد لا تكون ذاكرة الـ heap الجاني الرئيسيّ |
Thread Count |
ثابت في معظمه | يبدو تسريب thread أقلّ احتمالاً |
| موقع التعطّل | تنوّع قليلاً في كلّ مرّة | يبدو عطل ثانويّ محتملاً |
عند تلك النقطة، تضيّقت مساحة البحث كثيراً.
بدا من الأكثر طبيعيّةً قراءة الحالة ليس على أنّها “يتعطّل بعد شهر”، بل على أنّها “شيء ما يتسرّب شيئاً فشيئاً أثناء التشغيل، وهذا هو سبب تعطّله بعد شهر”.
3.3. نقطة التسريب الفعليّة
كان السبب النهائيّ هو نسيان إغلاق event handle أُنشئ على مسار فشل تهيئة أثناء إعادة اتّصال الكاميرا.
في صورة مبسّطة، بدا التدفّق هكذا:
sequenceDiagram
participant App as Control app
participant OS as Windows
participant SDK as Camera SDK
App->>OS: CreateEvent
App->>SDK: Register callback
SDK-->>App: Partial failure / timeout
Note over App: failure path returns
Note over App: CloseHandle is never called
loop many reconnects
App->>OS: Handle Count rises little by little
end
App->>OS: Next CreateEvent / Open
OS-->>App: Failure
App-->>App: Secondary crash
من الناحية المفهوميّة، كان الكود يبدو كهذا النوع من التسريب:
handle = CreateEvent(...)
if (!RegisterCallback(handle))
{
return Error; // CloseHandle(handle) is missing
}
if (!StartAcquisition())
{
return Error; // close is also missing here
}
...
CloseHandle(handle)
سبب فوات الاختبارات القصيرة لهذا واضح أيضاً نسبيّاً:
- في بدء التشغيل العاديّ -> الإيقاف العاديّ، يُغلق handle
- يحدث الفشل فقط أثناء إعادة الاتّصال
- لا يوجد اختبار يقود ذلك المسار للفشل بشكل متكرّر بحجم كبير
- في الإنتاج، يتراكم التسريب ببطء على مدى أسابيع
لذلك كانت البنية: غير مرئيّ إذا نظرت إلى المسار الطبيعيّ فقط، لكنّه تسريب عاديّ جدّاً على المسار غير الطبيعيّ.
الإصلاح نفسه لم يكن مبهرجاً:
- قرّب مسؤوليّات
create/openوclose/disposeمن بعضها البعض - تأكّد من تحرير الموارد دائماً حتّى عند الفشل الجزئيّ، على سبيل المثال باستخدام
finallyأو destructor أو session object - اجعل الملكيّة (ownership) صريحةً قبل وبعد تسجيل callback أو بدء الالتقاط
- عبّر عن “من يغلق هذا” كمسؤوليّة في الكود وليس كتعليق
هذه ليست خدعة خاصّة بقدر ما هي تصميم لدورة الحياة مدمج في الكود.
4. كيف ضيّقنا نطاق التحقيق
4.1. اضغط إعادة الإنتاج بدلاً من الانتظار شهراً آخر
في هذا النوع من التحقيقات، انتظار شهر في كلّ مرّة هو ببساطة استراتيجيّة سيّئة.
ما تريد فعله هو قيادة مسار الحافّة المشبوه عدّة مرّات في وقت قصير.
في هذه الحالة، ضُغطت إعادة الإنتاج بحلقات كهذه:
flowchart LR
A["Start"] --> B["Open camera"]
B --> C["Start acquisition"]
C --> D["Simulated timeout / disconnect"]
D --> E["Reconnect"]
E --> F["Resume acquisition"]
F --> G{"Repeat N times"}
G -- yes --> D
G -- no --> H["Check the final delta"]
النقطة هي قضاء الوقت على حواف دورة الحياة، وليس على وقت “إنّه يلتقط الإطارات بشكل صحيح” الطبيعيّ.
السيناريوهات التالية تساعد:
- شغّل
open -> start -> stop -> closeبحجم كبير - احقن timeouts عمداً وافرض إعادات الاتّصال
- افشل مباشرةً بعد تسجيل callback
- ضمّن مقاطعة قطع الاتّصال ومقاطعة إعادة الاتّصال وسباقات الإيقاف
لست بحاجة إلى إعادة تشغيل شهر كامل من الإنتاج بشكل مثاليّ.
عادةً ما يكون الوطء على حافّة دورة الحياة التي تشكّ فيها آلاف المرّات أكثر فاعليّةً بكثير.
4.2. انظر إلى ميل Handle Count
في تحقيقات handle leak، يمكن أن تكون القيم المطلقة وحدها مضلّلة.
ما يهمّ هو ما إذا كان العدد يعود بعد عمليّة من المفترض أن تحرّر الموارد، وكم ينمو لكلّ دورة متكرّرة.
تسلسل عمليّ هو:
- تحديد baseline بعد warm-up
- تسجيل
Handle Countبعد إعادة الاتّصال / start-stop / close - فحص الفرق لكلّ دورة
- فحص الميل عبر عدّة دورات أيضاً
على سبيل المثال:
leakSlope =
(currentHandleCount - baselineHandleCount)
/ reconnectCount
ما إذا كانت قيمة مطلقة مثل 2000 عاليةً أم منخفضةً يعتمد على التطبيق.
لكن إذا أضافت إعادة اتّصال واحدة حوالي +1 ولا تعود أبداً، فهذا مشبوه جدّاً.
من المفيد أيضاً عدم النظر إلى Handle Count وحده.
كحدّ أدنى، سجّله مع:
Handle CountPrivate BytesThread CountReconnectCount- المرحلة (phase) الحاليّة
هذا يخبرك بسرعة ما إذا كانت الذاكرة تنمو، أو الـ threads تنمو، أو إعادات الاتّصال تعود مع موارد لا تزال غير متوازنة.
4.3. قارن create/open مع close/dispose
حتّى عندما يبدو Handle Count على مستوى العمليّة بأكمله مشبوهاً، فإنّ ذلك وحده لا يخبرك بموقع التسريب.
الشيء التالي الذي تحتاجه هو تسجيل يُظهر دورة حياة الموارد كأزواج متطابقة.
على سبيل المثال، سجلّات منظّمة مثل هذه:
CameraSession session=421 cameraId=CAM01 phase=ReconnectStart reason=FrameTimeout handleCount=1824 privateBytesMB=418
CameraResource session=421 resourceId=evt-884 kind=Event name=FrameReady action=Create osHandle=0x00000ABC handleCount=1825
CameraResource session=421 resourceId=evt-884 kind=Event name=FrameReady action=Close osHandle=0x00000ABC handleCount=1824
النقطة المهمّة هي عدم الاعتماد على osHandle فقط.
يمكن إعادة استخدام قيم handle في Windows لاحقاً، لذا في السجلّات يكون من الأسهل بكثير متابعة القصّة إذا قمت بتضمين على الأقلّ:
sessionIdresourceIdkindaction(Create/Open/Register/Close/Dispose/Unregister)osHandlephase
هذا يجعل من الأسهل بكثير العثور على تدفّقات أحاديّة الجناح حيث يوجد Create لكن لا يوجد Close.
4.4. ابحث عن المكان الذي تسرّب فيه handle، لا فقط عن مكان وقوع التعطّل
هذه النقطة مهمّة جدّاً.
تبدو عمليّات handle leak غالباً هكذا:
- سطر التعطّل: فشل
CreateEvent - التسريب الحقيقيّ: كان
CloseHandleمفقوداً على مسار فشل لأيّام
بعبارة أخرى، فإنّ API الذي يتعطّل أخيراً غالباً ما يكون نقطة خروج الضرر، وليس نقطة دخول السبب.
لذا فإنّ ترتيب التحقيق عادةً ما يكون أفضل هكذا:
- انظر إلى أيّ مورد يستمرّ في النموّ
- انظر إلى أيّ حدود عمليّات يفشل في العودة
- ابحث عن المكان الذي يكون فيه زوج
create/openوclose/disposeمكسوراً - ثمّ فقط اقرأ موقع التعطّل النهائيّ
هذا الترتيب يجعل من الأقلّ احتمالاً بكثير أن تضيع.
5. ما هي السجلّات اللازمة لمنع تكرار الحادث
5.1. الحدّ الأدنى الذي يستحقّ الاحتفاظ به
ما ساعد في هذا التحقيق لم يكن “إضافة المزيد من السجلّات فحسب”.
كان إضافة المزيد من المعلومات التي ستسمح لنا لاحقاً بالوصول إلى السبب.
كحدّ أدنى، من المفيد الاحتفاظ بما يلي:
| الفئة | الحقول الدنيا التي تستحقّ الاحتفاظ بها | السبب |
|---|---|---|
| سياق العمليّة | cameraId، sessionId، operationId، reconnectCount، phase |
لربط حدث بالعمليّة الدقيقة ودورة إعادة المحاولة |
| موارد العمليّة | handleCount، privateBytes، workingSet، threadCount |
لتقسيم ما ينمو فعلاً |
| دورة حياة الموارد | action، resourceId، kind، osHandle، owner |
لمتابعة create/open مقابل close/dispose |
| نتائج الاستدعاءات الخارجيّة | win32Error، HRESULT، sdkError، timeoutMs |
لمقارنة أنواع الفشل لاحقاً |
| انتقالات الحالة | OpenStart، OpenDone، ReconnectStart، ReconnectDone، ShutdownStart، إلخ. |
لمعرفة أيّ مرحلة انهارت |
| بيئة التشغيل | pid، tid، buildVersion، machineName |
لمطابقة الـ dumps والرموز ومنتجات النشر |
هذا ليس كلّ شيء.
لكن بدون هذا القدر على الأقلّ، تتدهور السجلّات بسهولة إلى “نحن نعرف فقط أنّه تعطّل”.
5.2. السجلّات التي عزّزناها فعلاً
في هذه الحالة، تمّ تعزيز التسجيل في أربعة اتّجاهات:
- heartbeat دوريّ
- إصدار
Handle Count/Private Bytes/Thread Count/ReconnectCountكلّ 1 إلى 5 دقائق
- إصدار
- سجلّات حدود session الكاميرا
OpenStartCallbackRegisteredAcquisitionStartTimeoutDetectedReconnectStartReconnectDoneCloseStartCloseDone
- سجلّات دورة حياة الموارد
Create/Open/RegisterوClose/Dispose/Unregisterللأحداث والـ threads والملفّات والمؤقّتات وtokens تسجيل SDK
- توحيد الأخطاء
- بدلاً من الاكتفاء برسالة الاستثناء، إصدار
win32ErrorوHRESULTوsdkErrorوphaseمعاً
- بدلاً من الاكتفاء برسالة الاستثناء، إصدار
نقطة مهمّة هي الحفاظ على شكل سجلّ متّسق بين النجاح والفشل.
إذا تحوّلت الحالات غير الطبيعيّة إلى تنسيق مختلف تماماً، يصبح التجميع لاحقاً أصعب.
5.3. ما مدى دقّة دقّة السجلّ المطلوبة
الخطأ المغري هو “تسجيل كلّ شيء فقط في INFO”.
لكن إذا فعلت ذلك، فستنتهي لاحقاً بقراءة جدار من الضوضاء.
التقسيم الواقعيّ عادةً هو:
- مراقبة دوريّة
Handle Count،Private Bytes،Thread Count،ReconnectCount
- حدود العمليّات
- بدء / انتهاء / فشل session
- حدود الموارد
create/open/registerوclose/dispose/unregister
- تفاصيل الحالات غير الطبيعيّة
- رموز الأخطاء، الـ stack traces، شروط تشغيل dump
السجلّات التفصيليّة لكلّ frame عادةً ما تكون غير ضروريّة.
بالنسبة لأعطال التشغيل طويل الأمد، فإنّ السجلّات التي تجعل من الممكن قراءة أيّ مسؤوليّة فتحت مورداً وأيّ مسؤوليّة أغلقته ذات قيمة أكبر بكثير.
6. دليل قواعد عامّة تقريبيّة
- يحدث التعطّل فقط بعد أيّام أو أسابيع
- أوّلاً أضف heartbeat لـ
Handle Count/Private Bytes/Thread Count
- أوّلاً أضف heartbeat لـ
- يحتوي النظام على مسارات إعادة المحاولة / إعادة الاتّصال / الإيقاف
- ابنِ harness يقود تلك الحدود فقط بحجم كبير
- يستخدم التطبيق الكثير من native SDK أو P/Invoke أو Win32
- تقنيّات Application Verifier في الجزء 2 تستحقّ الاستخدام بشكل خاصّ
- يتضمّن التطبيق أيضاً واجهة مستخدم رسوميّة
- بالإضافة إلى
Handle Count، انظر أيضاً إلىGDI ObjectsوUSER Objects
- بالإضافة إلى
- الاستثناء النهائيّ لا يخبرك بشيء تقريباً
- عادةً ما يكون من الأسرع تحسين السجلّات المنظّمة لدورة حياة العمليّة / session / المورد أوّلاً
النقطة الأخيرة مهمّة كثيراً.
في تحقيق العيوب، فإنّ العامل الحاسم في كثير من الأحيان ليس تقنيّة التحليل نفسها بل ما إذا كان النظام قد جُعل قابلاً للمراقبة في المقام الأوّل.
7. الخلاصة
النقاط المهمّة التي يجب الاحتفاظ بها هي هذه.
كيفيّة قراءة الأعراض:
- إذا تعطّل التطبيق فقط بعد التشغيل طويل الأمد، انظر إلى
Handle Countبالإضافة إلى الذاكرة - تميل عمليّات handle leak إلى الاختباء على مسارات الفشل غير الطبيعيّة بدلاً من المسار الطبيعيّ
- موقع التعطّل غالباً ما لا يكون موقع التسريب بل فقط نقطة خروج الضرر الثانويّ
تغييرات التصميم التي تساعد في منع التكرار:
- قرّب مسؤوليّات
create/openوclose/disposeمن بعضها البعض - احتفظ بسجلّات غنيّة بالسياق حسب session / operation
- سجّل كلّاً من مقاييس الموارد على مستوى العمليّة وأحداث دورة حياة كلّ مورد
استراتيجيّة الاختبار التي تساعد:
- لا تنتظر إعادة إنتاج بمقياس شهور؛ قُد timeout / إعادة الاتّصال / الإيقاف في حلقة قصيرة
- لا تجعل “لا يتعطّل” معيار القبول الوحيد؛ اشترط أيضاً أنّه “عندما يتعطّل، يمكننا تتبّعه”
- في الجزء 2، استخدم Application Verifier لإظهار حالات الفشل التي يصعب تشغيلها مثل استنفاد الموارد وحالات handle الشاذّة في وقت أبكر
في تطبيقات التحكّم، من المهمّ أن يعمل المسار الطبيعيّ.
لكن في التشغيل طويل الأمد، من المهمّ جدّاً أيضاً معرفة ما الذي حدث عندما تعطّل.
عمليّات handle leak هي بالضبط نوع الأخطاء حيث يؤتي هذا الفرق ثماره.
بدلاً من النظر فقط إلى لحظة التعطّل، انظر إلى النموّ والحدود وتماثل دورة الحياة. هذا يجعلها أسهل بكثير في التتبّع.
8. المراجع
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
حين يتعطّل تطبيق التحكّم بكاميرا صناعيّة فجأةً بعد شهر (الجزء الثاني) - ما هو Application Verifier وكيف نبني بنية اختبار لمسارات الفشل
كيف يكشف Application Verifier عن تسريبات handle ومسارات الفشل مبكراً عبر Low Resource Simulation و!htrace، لبناء بنية اختبار عمليّة لتطبي...
حين تتوقّف حركة TCP للكاميرا الصناعيّة لعدّة ثوانٍ - كيف نضيق نطاق انتظار إعادة الإرسال باستخدام طوابع زمنيّة RFC1323
تشريح لتوقّفات TCP المتقطّعة لعدّة ثوانٍ بين تطبيق المضيف والكاميرا الصناعيّة، مع استخدام Wireshark وفقد الحزم وطوابع RFC1323 الزمنيّة لت...
المزالق الشائعة في تطوير مكوّنات COM و OCX / ActiveX - فخاخ Visual Studio بين 32-bit و 64-bit، والتسجيل، وصلاحيّات المسؤول
دليل عمليّ يكشف الأسباب الحقيقيّة لإخفاق مكوّنات COM و OCX و ActiveX: عدم تطابق 32-bit / 64-bit مع Visual Studio 2022، وأخطاء regsvr32 و ...
ما هو ClickOnce - كيف يعمل، وكيف تعمل التحديثات، ومتى يلائم العمل الفعليّ ومتى لا يلائمه
نظرة عمليّة على ClickOnce لتوزيع تطبيقات .NET لسطح مكتب Windows: كيف تعمل manifests والتحديثات والـ cache، ومتى يلائم العمل الداخليّ ومتى...
كيف نستعمل Windows Sandbox لتسريع التحقّق من تطبيقات Windows - صلاحيّات المسؤول والبيئات النظيفة وإعادة إنتاج حالات نقص الصلاحيّات أو الموارد
مرشد عمليّ يبيّن كيف يسرّع Windows Sandbox التحقّق من تطبيقات Windows، عبر ملفّات .wsb لكلّ سيناريو وفحوصات المستخدم القياسيّ ومحاكاة شُح...
دراسة حالة ذات صلة
صفحة دراسة حالة توضّح بنية مشابهة للتشخيص أو تحديد الأولويات أو إعادة التصميم.
دراسة حالة: تتبّع انهيار التشغيل الطويل حتى تسرّب المقابض
دراسة حالة لتحويل انهيار على مقياس شهري إلى تحقيق في تسرّب المقابض عبر نقاط مراقبة أفضل وتسجيل محسّن.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.
روابط عامة