Howto share filehandles between threads?

S

Sako

I am trying to teach myself perl by writing a program I've been meaning
to implement, so I am pretty green in perl. I'm having problems sharing
filehandles opened by a thread - been RTFM for a few days, but am having
no luck.

I am attempting to write a threaded server program that listens on a
socket for requests, then passes the socket's filehandle to an event
processor routine, while the listener thread keeps on listening.
However, I cannot seem to be able to successfully pass the filehandle
from the listener thread to the event handler.

For testing purposes, I've tried to get the logic down using a thread to
open a filehandle and pass it back to the non-threaded routine as follows:

--------- start ------------
#!/usr/bin/perl

use threads;
use threads::shared;

my $FH : shared;

threads->new(sub {
open($LFH,"< /tmp/junk") || die $!;
$FH=$LFH;
print "[$FH]\n";
#while (<$LFH>) {print "> $_";}
})->join;

print "[$FH]\n";
while (<$FH>) {print "> $_";}

---------- end -------------

Running it gives:
"thread failed to start: Invalid value for shared scalar at ./x.pl line 10."

Any help on how to share a filehandle opened in a thread would be
GREATLY appreciated.

TIA
 
Z

zentara

Any help on how to share a filehandle opened in a thread would be
GREATLY appreciated.

Hi, BrowserUk figured it out on perlmonks awhile back, what you
need to do basically is get the fileno of the filehandle, and pass
it around through shared variables.

See:
http://perlmonks.org?node_id=395513


Also of interest may be
http://perlmonks.org?node_id=501725

Here is a little demo I worked up for myself.

#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

my %shash;
#share(%shash); #will work only for first level keys
my %hash;

share ($shash{'go'});
share ($shash{'fileno'});
share ($shash{'pid'});
share ($shash{'die'});

$shash{'go'} = 0;
$shash{'fileno'} = -1;
$shash{'pid'} = -1;
$shash{'die'} = 0;

$hash{'thread'} = threads->new(\&work);

$shash{'go'} = 1;

sleep 1; # cheap hack to allow thread to setup

my $fileno = $shash{'fileno'};
open (my $fh, "<&=$fileno") or warn "$!\n";

while ( <$fh> ){ print "In main-> $_"; }

#wait for keypress to keep main thread alive
<>;

# control-c to exit

##################################################################
sub work{
$|++;
while(1){
if($shash{'die'} == 1){ return };

if ( $shash{'go'} == 1 ){

my $pid = open(FH, "top -b |" ) or warn "$!\n";
my $fileno = fileno(FH);
print "fileno->$fileno\n";
$shash{'fileno'} = $fileno;

$shash{'go'} = 0; #turn off self before returning
}else
{ sleep 1 }
}
}
#####################################################################
__END__
 
S

Sako

zentara said:
Hi, BrowserUk figured it out on perlmonks awhile back, what you
need to do basically is get the fileno of the filehandle, and pass
it around through shared variables.

See:
http://perlmonks.org?node_id=395513


Also of interest may be
http://perlmonks.org?node_id=501725

Here is a little demo I worked up for myself.

#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

my %shash;
#share(%shash); #will work only for first level keys
my %hash;

share ($shash{'go'});
share ($shash{'fileno'});
share ($shash{'pid'});
share ($shash{'die'});

$shash{'go'} = 0;
$shash{'fileno'} = -1;
$shash{'pid'} = -1;
$shash{'die'} = 0;

$hash{'thread'} = threads->new(\&work);

$shash{'go'} = 1;

sleep 1; # cheap hack to allow thread to setup

my $fileno = $shash{'fileno'};
open (my $fh, "<&=$fileno") or warn "$!\n";

while ( <$fh> ){ print "In main-> $_"; }

#wait for keypress to keep main thread alive
<>;

# control-c to exit

##################################################################
sub work{
$|++;
while(1){
if($shash{'die'} == 1){ return };

if ( $shash{'go'} == 1 ){

my $pid = open(FH, "top -b |" ) or warn "$!\n";
my $fileno = fileno(FH);
print "fileno->$fileno\n";
$shash{'fileno'} = $fileno;

$shash{'go'} = 0; #turn off self before returning
}else
{ sleep 1 }
}
}
#####################################################################
__END__
Thx much!
 
X

xhoster

Sako said:
I am trying to teach myself perl by writing a program I've been meaning
to implement, so I am pretty green in perl. I'm having problems sharing
filehandles opened by a thread - been RTFM for a few days, but am having
no luck.

I think Perl is a great language, but not for threading. You should
probably either choose a different task to be your introduction to Perl;
or, if threading is central to what you do, then choose to learn a
different language.

I am attempting to write a threaded server program that listens on a
socket for requests, then passes the socket's filehandle to an event
processor routine, while the listener thread keeps on listening.
However, I cannot seem to be able to successfully pass the filehandle
from the listener thread to the event handler.

If you are going to start a new thread for each session (which I wouldn't
recommend, but then again I don't recommend this whole situation), then I
wouldn't pass the handle at all. Simply stash the handle in a variable
whose scopes spans both the listener and the event handler. A child thread
glombs onto whatever handle was stored in a variable at the time it was
created. This requires the listener to be the "master" thread.

use strict;
use warnings;
use threads;
use threads::shared;
$|=1;
my $conn;
foreach (1..10) {
undef $conn;
open $conn, ">/tmp/foo_$_" or die $!;
threads->create("do_it", $_);
};
$_->join foreach threads->list();
sub do_it {
my $request=shift;
foreach (1..100)
{
print $conn "$request $_\n";
select undef,undef,undef, 0.1;
};
};

Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top