2016-07-29 63 views
2

我有一個任務,我在一個線程中等待連接並將它們轉發到另一個線程。 也許我誤解了一些東西,但爲什麼我不能在主線程中重新打開文件描述符?線程之間轉發/傳遞文件描述符

非常簡化的代碼:

sub inthread { 
    $socket = new IO::Socket::INET (...); 
    # ... 
    while (my $client = $socket->accept()) { 
     #if i print STDOUT, (fileno $client); # there i'll get 4 
     push (@shared, fileno $client); 
    } 
} 


sub mainthread { 
    if (scalar @shared) { 
     $fd = shift @shared; 
     # if i print (fileno $fd); # there i'll get 4 
     open my $f, "<&=$fd" or die " error $!"; ### error here: Can't open 4: Bad file descriptor 
     while (<$f>) { ... } 
    } 
} 

threads->create(\&inthread); 
while(1) { mainthread; } 

整個代碼是有http://dpaste.com/3381RKV

測試:

perl -w ./testcode.pl --port=10102 & 
wget -O - http://127.0.0.1:10102/
+1

注意:總是'use use strict;使用警告'all';'!你有許多不正確的範圍變量,這會幫助你發現這些問題。 – ikegami

+2

注意:'<'應該是'+ <'這裏。 – ikegami

+0

@ikegami相同 –

回答

6

my $client創建作用域循環體的變量。通過結束時,最後一個對包含句柄的引用被放棄,釋放文件句柄,該句柄關閉了關聯的文件描述符。 [1]

這發生在另一個線程到達open <&=之前,因此當您嘗試爲它創建新文件句柄時,文件描述符不再有效。

自給示範:

#!/usr/bin/perl 

use strict; 
use warnings; 

my $fd; 

{ 
    open(my $fh, '<', $0) 
     or die($!); 

    $fd = fileno($fh); 
}        # File handle closed here. 

{ 
    open(my $fh, '<&=', $fd) 
     or die($!);    # Bad file descriptor 
} 

你必須確保文件句柄不會被過早關閉。您可以將它們存儲在數組或散列鍵中,而另一個線程可以讓父線程通過另一個共享結構知道哪些句柄不再需要它。


  1. 在你的代碼中的註釋鏈接(相對於您發佈的代碼),當你調用close $client;的文件描述符,而不是關閉。
+0

在線程中,我只需要接受連接,然後線程繼續執行其等待新連接的工作。它從不關閉文件描述符。所有文件讀取/寫入和關閉在另一個工作線程中執行。所以我知道它並沒有關閉FD。而且我確切地知道該連接不會通過客戶端丟失,因爲它使用其他軟件進行測試。 –

+0

「它永遠不會關閉文件描述符」,你顯示的代碼的確如此。下一次你賦值給'$ a'時,你刪除最後一個引用'$ a'先前包含的句柄,導致底層fd被關閉。 – ikegami

+0

請解釋如果它隱含關閉文件描述符 我在代碼中有一個錯誤:$ a = $ socket-> accept()應該是我的$ a = $ socket-> accept() –