2012-05-04 25 views
6

Tôi đang cố gắng giải đố thông qua một tài liệu mà tôi thấy trong tài liệu perlipc.Lỗi trong tài liệu perlipc?

Nếu bạn đang viết thư cho một đường ống, bạn cũng nên bẫy SIGPIPE. Nếu không, suy nghĩ về những gì xảy ra khi bạn bắt đầu một đường ống đến lệnh không tồn tại: mở() sẽ có khả năng thành công (chỉ phản ánh thành công của ngã ba), nhưng sau đó đầu ra của bạn sẽ không thành công - một cách ngoạn mục. Perl không thể biết liệu lệnh này có hoạt động không vì lệnh của bạn thực sự đang chạy trong một quy trình riêng biệt có exec() có thể không thành công. Vì vậy, trong khi độc giả của các lệnh không có thật trả lại chỉ là một kết thúc nhanh chóng của tập tin, các nhà văn để lệnh không có thật sẽ kích hoạt một tín hiệu họ muốn được chuẩn bị tốt hơn để xử lý. Xem xét:

open(FH, "|bogus") or die "can't fork: $!"; 
    print FH "bang\n" or die "can't write: $!"; 
    close FH   or die "can't close: $!"; 

Điều đó sẽ không thổi lên cho đến khi kết thúc, và nó sẽ nổ tung với một SIGPIPE . Để nắm bắt nó, bạn có thể sử dụng này:

$SIG{PIPE} = 'IGNORE'; 
    open(FH, "|bogus") or die "can't fork: $!"; 
    print FH "bang\n" or die "can't write: $!"; 
    close FH   or die "can't close: status=$?"; 

Nếu tôi đọc mà chính xác, nó nói rằng phiên bản đầu tiên có thể sẽ không chết cho đến khi kết thúc trận chung kết.

Tuy nhiên, điều đó không xảy ra trên hộp OS X của tôi (Perl phiên bản 5.8.9 đến 5.15.9). Nó thổi lên trên open với một "không thể ngã ba: Không có tập tin hoặc thư mục" bất kể có hay không tôi có dòng $ SIG {PIPE} trong đó.

Tôi hiểu lầm điều gì?

+0

Tôi nghĩ rằng 'mở' đã được thay đổi để báo cáo tốt hơn trường hợp đó và' perlipc' không được cập nhật; bạn vẫn có thể nhận được hành vi được ghi lại, nhưng bạn cần sử dụng cơ chế 'mở (..., '| -')' tiết hơn. – geekosaur

+0

geekosaur: chuyển sang 'mở $ fh của tôi', '| -', '' không có thật '' hoặc chết 'cho cùng một lỗi. – Ovid

+0

Erm. Tôi có nghĩa là * thực sự * đường dài, nơi bạn không chỉ định một lệnh nào cả nhưng thay vào đó bản thân kịch bản là 'fork' và bạn chạy' exec' trong đứa trẻ. – geekosaur

Trả lời

0

Cùng đầu ra trên Perl của tôi, v5.14.2, Ubuntu 12.04:

$ perl 
    open(FH, "|bogus") or die "can't fork: $!"; 
    print FH "bang\n" or die "can't write: $!"; 
    close FH   or die "can't close: $!"; 
can't fork: No such file or directory at - line 1. 

Và lỗi đó là lẻ, vì nó không có gì để làm với forking - họ phải có thêm một số lookahead-đoán để xem nếu nó có thể thực hiện bogus. (Đó sẽ là điều kiện cuộc đua ở mức tốt nhất, nhưng có khả năng cung cấp xử lý lỗi tốt hơn đáng kể trong trường hợp phổ biến; và chỉ là bất tiện như hành vi cũ khi cuộc đua bị mất.)

+0

Không nhất thiết phải đoán; cho rằng Perl đã cố gắng sử dụng một tìm kiếm 'PATH' nội bộ và' exec' nếu không có siêu ký tự shell nào có liên quan, nó đã phát hiện trước "không tìm thấy" trước đó. – geekosaur

+0

@geekosaur: nhưng 'bogus' có thể nằm trong' PATH' _and executable_ khi cuộc gọi 'execve()' cuối cùng xuất hiện. Có, nó chỉ mất một phần nghìn giây, nhưng [điều kiện chủng tộc hiếm khi lành tính này] (http://en.wikipedia.org/wiki/Time_of_check_to_time_of_use). :) – sarnold

+0

Tôi nghĩ rằng chỉ tính như một điều kiện chủng tộc nếu bạn đang viết mã đó với kỳ vọng cụ thể là nó sẽ thất bại. – geekosaur

Các vấn đề liên quan