2012-09-29 15 views
8

Imagine đoạn mã sau Perl (ở đây trong mã giả):Phát hành đàn trong trường hợp có lỗi?

successfully acquired flock for FILEHANDLER  # line 1 
some error or maybe simply a call to exit()  # line 2 
close FILEHANDLER (which also releases the lock) # line 3 

Trong trường hợp này tôi sẽ không phát hành các khóa, như kịch bản Perl kết thúc bằng dòng 2. Trong trường hợp đó, là khóa bao giờ phát hành bởi hệ điều hành? Liệu nó có thấy "hey, tập lệnh đã lấy khóa bị rơi" và nhả khóa không? Nó có nhả khóa ngay lập tức không? Ngoài ra, là có một trường hợp Perl chạy cho mỗi kịch bản, để nó rõ ràng mà kịch bản đã bị rơi/dừng lại mà không phát hành khóa?

Trả lời

24

Trong trường hợp đó, khóa có bao giờ được hệ điều hành phát hành không?
Liệu nó có thấy "này, tập lệnh lấy khóa bị rơi" và nhả khóa không?
Nó có khóa ngay lập tức không?

Tất cả các câu hỏi này phụ thuộc vào hệ thống. Perl 5 không thực hiện chức năng khóa tệp, nó chỉ cung cấp giao diện chung cho các khóa flock(2), fcntl(2) hoặc lockf(3) (tùy thuộc vào những gì có sẵn trong hệ điều hành). Cũng có thể có sự khác biệt giữa những gì xảy ra khi một chương trình thoát, phân đoạn hoặc bị giết bằng một sigkill.

Xét nghiệm nhanh dưới Linux cho thấy một khóa được lấy ra trong điều kiện thoát bình thường:

$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"' 
got lock 
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"' 
got lock 

Hãy xem những gì sẽ xảy ra khi chúng ta die:

$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"' 
got lock 
died at -e line 1. 
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"' 
got lock 
died at -e line 1. 

Để có được một segfault, chúng tôi sẽ cần truy cập vào C, tôi đang sử dụng Inline để tải xuống:

$ cat segfault.pl 
#!/usr/bin/perl 

use strict; 
use warnings; 

use Inline "C"; 

open my $fh, ">", "f" or die $!; 

print flock($fh, 6) ? "got lock" : "was already locked", "\n"; 

crash(); 

__DATA__ 
__C__ 

void crash() { 
    int* ptr = NULL; 
    *ptr = 5; 
} 
$ perl segfault.pl 
got lock 
Segmentation fault 
$ perl segfault.pl 
got lock 
Segmentation fault 

Và cuối cùng, đây là những gì sẽ xảy ra khi một chương trình được gửi SIGKILL:

$ cat fork.pl 
#!/usr/bin/perl 

use strict; 
use warnings; 

$SIG{CHLD} = "IGNORE"; #auto-reap children 

die "could not fork: $!" unless defined(my $pid = fork); 
unless ($pid) { 
    #child 
    open my $fh, ">", "f" or die $!; 
    print flock($fh, 6) ? "got lock" : "was already locked", "\n"; 
    sleep(100); 
    exit; 
} 

kill 9, $pid; 

die "could not fork: $!" unless defined($pid = fork); 
unless ($pid) { 
    #child 
    open my $fh, ">", "f" or die $!; 
    print flock($fh, 6) ? "got lock" : "was already locked", "\n"; 
    exit; 
} 
$ perl fork.pl 
got lock 
got lock 

Từ những thí nghiệm này, chúng ta có thể thấy rằng các khóa được phát hành trong Linux cho từng trường hợp, bạn đã quan tâm.

Ngoài ra, có một trường hợp perl đang chạy cho từng tập lệnh hay không, sao cho tập lệnh đó bị lỗi/dừng mà không giải phóng khóa?

Có, Perl 5 có một quá trình perl cho mỗi tập lệnh. Ngay cả khi bạn ngã ba, đứa trẻ có quy trình riêng của mình là perl. Luồng không cung cấp quy trình perl riêng biệt.

Lưu ý: nếu quy trình gốc được khóa và không cho khóa trước khi khóa, thì trẻ sẽ có cùng khóa ngay cả khi cha mẹ thoát.

+3

câu trả lời chi tiết tuyệt vời, cảm ơn bạn rất nhiều! cũng nhờ soulSurfer2010 cho câu trả lời ngắn nhưng vẫn chính xác và mang tính thông tin! –

1

Khi chương trình thoát, hệ điều hành sẽ tự động giải phóng tất cả các khóa được chương trình mua lại và đóng tất cả các tệp do chương trình mở.

+0

Câu trả lời này không hữu ích nếu không có bằng chứng nào cho thấy bạn đúng. –