לדלג לתוכן

פתרון מחזור חיי תהליך ובידוד משאבים

בסיום רגיל הילד מחזיר שבע. במסלול timeout ההורה מבקש TerminateJobObject עם קוד 102, ולכן זה הקוד שהניסוי מצפה לראות לאחר שהסיום הושלם. עצם הצלחת הבקשה אינה מחליפה המתנה.

אפשר להוסיף לילד marker מקומי, אך חשוב לבצע כתיבה שאפשר להבחין בה ולא להסיק מהיעדר טקסט בלבד. הראיה העיקרית היא החוזה: termination כפוי אינו מסלול רגיל של stack unwinding ב־C++.

מסלול rollback מפורש יכול להשתמש בפונקציית עזר כזו. היא מצטרפת לתוכנית ומחזירה אם הצלחנו לאמת סיום בתוך deadline; היא אינה מסתירה כשל שני.

bool stop_created_child(HANDLE process, UINT code) {
    if (!TerminateProcess(process, code)) {
        const DWORD error = GetLastError();
        if (WaitForSingleObject(process, 0) != WAIT_OBJECT_0) {
            std::printf("termination error=%lu\n", error);
            return false;
        }
        return true;
    }
    const DWORD wait = WaitForSingleObject(process, 5000);
    if (wait != WAIT_OBJECT_0) {
        std::printf("termination wait=%lu\n", wait);
        return false;
    }
    return true;
}

הפונקציה מטפלת גם במצב שבו התהליך כבר הסתיים עד שביקשנו להרוג אותו. היא אינה מפרשת כל ERROR_ACCESS_DENIED כהוכחה לכך; היא בודקת בנפרד אם האובייקט מסומן כסיום. אם התוצאה עדיין אינה ידועה, ההורה מדווח כשל פיקוח.

בדיקת job קיים משתמשת ב־IsProcessInJob עם handle התהליך הנוכחי ו־job ריק לפי החוזה. תוצאה חיובית מסבירה שיש הקשר נוסף, אך אינה אומרת מראש שכל nested job ייכשל.

פרוטוקול שיתופי כולל מצב running, בקשת stopping, מצב draining ולבסוף exited. לאחר בקשת stop ההורה ממתין לאישור או לסיום תהליך עד deadline. רק אם הילד אינו מתקדם מפעילים fallback כפוי ומתעדים שלא התקבל אישור לשמירת מצב.

ה־job handle נשאר חי כל עוד רוצים שהקבוצה תמשיך לפעול תחת המדיניות. כאשר KILL_ON_JOB_CLOSE פעיל, סגירת ה־handle האחרון היא פעולה בעלת משמעות תפעולית. אסור להעביר אותו במקרה לילד ולצפות שסגירת עותק ההורה תהיה בהכרח הסגירה האחרונה.