לדלג לתוכן

פתרון הפעלה והקשחה

פתרון ראשון

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

פתרון שני

נוסיף אחרי קבלת המאזין את קטע הבדיקה הבא. הוא משתמש בנתיב מעבדה ייחודי תחת עץ שאמור להיות מוגן, ומדווח הצלחה בלתי צפויה בלי להשאיר קובץ מאחור.

let forbidden = format!("/usr/amit-write-probe-{}", std::process::id());
match OpenOptions::new().write(true).create_new(true).open(&forbidden) {
    Ok(file) => {
        drop(file);
        std::fs::remove_file(&forbidden)?;
        return Err(io::Error::other("unexpected write permission"));
    }
    Err(error) => println!("write blocked: {error}"),
}
let fd = unsafe { libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0) };
if fd >= 0 {
    drop(unsafe { OwnedFd::from_raw_fd(fd) });
    return Err(io::Error::other("unexpected socket creation"));
}
println!("socket creation blocked: {}", io::Error::last_os_error());

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

פתרון שלישי

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

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