קלט/פלט

close#

סגירת מטפל קובץ, פליטת המאגרים שלו, ושחרור ה־file descriptor התשתיתי.

close משלים כל קלט/פלט שהיה בהמתנה על FILEHANDLE, מפרק את מחסנית שכבות PerlIO, ומבקש מהקרנל לסגור את ה־descriptor. ערך ההחזרה מבדיל בין סגירה נקייה לבין סגירה שבה כתיבה ממואגרת נכשלה בדרך החוצה, שכבת PerlIO דיווחה על שגיאה, או - עבור pipes - תהליך הילד יצא בערך לא־אפס. ללא ארגומנט, close פועל על מטפל הקובץ הנבחר כעת (ראו select).

תקציר#

close FILEHANDLE
close EXPR
close

מה מקבלים בחזרה#

ערך אמת (1) על סגירה נקייה; שקר אחרת. החזרת שקר משמעה שאחד מהבאים השתבש:

  • לא ניתן היה לפלוט כתיבה ממואגרת שהייתה בהמתנה (דיסק מלא, pipe שבור, סוקט סגור).

  • שכבת PerlIO (לדוגמה :encoding(...), :gzip משכבת CPAN) דיווחה על שגיאה.

  • שגיאה דביקה קיימת־מראש כבר נרשמה על המטפל.

  • המטפל הגיע מ־open עם pipe והילד יצא בערך לא־אפס (או ש־syscall אחר המעורב בפירוק ה־pipe נכשל).

כאשר close מחזיר שקר, $! מחזיק את השגיאה מהפעולה שנכשלה ובטוח לקרוא ממנו. עבור מטפלי pipe, אם הבעיה היחידה הייתה יציאת ילד בערך לא־אפס, $! נקבע ל־0 והסטטוס של הילד מופיע ב־$? (ראו להלן).

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

close $fh
    or die "close $path failed: $!";

מצב גלובלי שהוא נוגע בו#

  • $! - נקבע ל־errno שנכשל כאשר close מחזיר שקר, כולל שגיאת פליטה בכתיבה הממוואגרת הסופית. מאופס ל־0 בסגירת pipe שבה הבעיה היחידה הייתה יציאת ילד בערך לא־אפס.

  • $? - עבור מטפלים מ־open עם pipe, נקבע לסטטוס ההמתנה של תהליך הילד: 8 הביטים התחתונים הם האות, 8 הביטים העליונים הם קוד היציאה (אותו קידוד כמו system).

  • ${^CHILD_ERROR_NATIVE} - עבור מטפלי pipe, נקבע לערך הסטטוס הגולמי של מערכת ההפעלה (לפני הקידוד הנייד של Perl).

  • $. - close מפורש על מטפל קלט מאפס את מספר השורה הנוכחי. סגירה מרומזת באמצעות פתיחה מחדש של אותו מטפל אינה מאפסת.

  • מטפל הקובץ הנבחר כעת (באמצעות select) - close ללא ארגומנט סוגר אותו.

דוגמאות#

סגירת קובץ רגיל ובדיקת כישלון פליטה:

open my $fh, ">", "out.txt" or die $!;
print {$fh} @records;
close $fh or die "flush to out.txt failed: $!";

סגירת pipe שנפתח לכתיבה ובחינת סטטוס היציאה של הילד. close ממתין לילד, ואז מאכלס את $?:

open(my $sort, "|-", "sort", ">", "foo")
    or die "can't start sort: $!";
# ... print records to $sort ...
close $sort
    or warn $! ? "error closing sort pipe: $!"
               : "sort exited with status " . ($? >> 8);

סגירת pipe שנפתח לקריאה, ולאחר מכן איסוף סטטוס היציאה של הפקודה. קוד היציאה הוא 8 הביטים העליונים של $?:

open(my $who, "-|", "who") or die $!;
my @lines = <$who>;
close $who;
my $exit = $? >> 8;

close חשוף סוגר את המטפל ש־select הפך לנוכחי לאחרונה, ואז משחזר את STDOUT כמטפל הנבחר:

open my $log, ">>", "app.log" or die $!;
my $old = select $log;
print "entry\n";
close;                       # closes $log (the selected handle)
select $old;

סגירת קצה הקריאה של pipe מוקדם גורמת לכותב לקבל SIGPIPE. אם לכותב אין מטפל, הוא ייהרג - יש לרוקן את ה־pipe תחילה אם נדרש שהכותב יצא בצורה נקייה:

open my $gen, "-|", "some-producer" or die $!;
while (<$gen>) { last if /^END/ }
1 while <$gen>;              # drain so the child finishes cleanly
close $gen or warn "producer failed: $!";

מקרי קצה#

  • close חשוף - ללא ארגומנט, סוגר את מטפל הקובץ הנבחר כעת. בתוכנית שהתחילה זה עתה זהו STDOUT; לאחר select($fh) זה $fh. לעיתים נדירות זה הרצוי מחוץ לקוד עם תחום הדוק.

  • פתיחה מחדש סוגרת בשבילך - open my $fh, ... על מטפל שכבר פתוח יסגור תחילה את ה־descriptor הישן. הסגירה המרומזת אינה מאפסת את $.; close מפורש כן מאפס. יש להשתמש ב־close מפורש כאשר מצב מספר־השורה חשוב.

  • יציאה מהתחום סוגרת מטפלים לקסיקליים - כאשר ההפניה האחרונה למטפל קובץ לקסיקלי יוצאת מהתחום, Perl סוגר אותו. אם סגירה מרומזת זו נכשלת (שגיאת פליטה, יציאת ילד בערך לא־אפס), Perl פולט אזהרה Warning: unable to close filehandle %s properly. יש לקרוא ל־close במפורש בנקודה שבה ניתן לבדוק את ערך ההחזרה ולהשתיק את האזהרה הזו.

  • מטפלים עקיפים - FILEHANDLE עשוי להיות כל ביטוי שמפיק מטפל קובץ שמיש: bareword (close STDERR), סקלר (close $fh), הפניה ל־glob (close \*FH), או מטפל מ־autovivification מ־open my $fh, ....

  • סגירת pipe ממתינה - סגירת מטפל pipe חוסמת עד שהילד יוצא, כך ש־$? מאוכלס עד הזמן ש־close מחזיר. תחת threads, אם אותו מטפל pipe עדיין פתוח ב־thread אחר, close מחזיר אמת מיד מבלי לאסוף את הילד.

  • סגירת pipe עם יציאה לא־אפסית - close מחזיר שקר וקובע את $! ל־0 כך ש־$! ? "$!" : "exit $?" מבחין בין כישלון ברמת מערכת ההפעלה לבין יציאה לא־אפסית רגילה.

  • מטפל סגור או לא תקף - סגירת מטפל שאינו פתוח קובעת את $! ל־"Bad file descriptor" ומחזירה שקר. תחת use warnings, נפלטת אזהרה close() on unopened filehandle.

  • STDIN / STDOUT / STDERR - ניתן לסגור אותם כמו כל מטפל אחר. ה־descriptor משוחרר וייעשה בו שימוש חוזר על־ידי ה־open הבא על המטפל הסטנדרטי, וכך עובד ההפניה הקלאסי open STDOUT, ">", "log".

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • open - מקבילה; open על מטפל שכבר פתוח מבצע close מרומז תחילה (אך אינו מאפס את $.)

  • print - print הממוואגר הסופי נפלט בתוך close, כך שההצלחה האמיתית של הכתיבה ידועה רק לאחר close

  • fileno - מספר ה־descriptor של מטפל; הופך לבלתי תקף לאחר ש־close מצליח

  • binmode - מחסנית השכבות שנקבעה על־ידי binmode מפורקת במהלך close, והפירוק שלה עצמו עלול להיכשל

  • $? - סטטוס יציאת הילד המאוכלס על־ידי close על מטפל pipe

  • $! - שגיאה מפעולת ה־close שנכשלה