I wrote a program that was monitoring three handles (pipes in this case). I want to do something when there's something to read on any of the pipes, and also when there's an error. Hence:
my $p1 = open (...) or die; my $p2 = open (...) or die; my $p3 = open (...) or die; my $BITS = ""; vec ($BITS, fileno ($_), 1) = 1 for $p1, $p2, $p3; while (1) { my $rbits = $BITS; my $ebits = $BITS; select ($rbits, undef, $ebits, TIMEOUT); if ($ebits) {raise_hell ()} if (vec ($rbits, fileno ($p1), 1) == 1) {something ()} if (vec ($rbits, fileno ($p2), 1) == 1) {something_else ()} if (vec ($rbits, fileno ($p3), 1) == 1) {another_thing ()} }But this didn't behave I wanted it to. Can you spot the mistake?
select ($rbits, undef, $ebits, TIMEOUT);
The first 3 arguments to select
are value/return - on input you give a bitmask of the file descriptors you are interested in, on output only the bits corresponding "interesting" file descriptors are set. So it's likely that after the first call to select
, all the bits were zeroed, and so for subsequent calls the arguments you passed in say that you're not interested in any file descriptors, so you never call any of your action functions. The solution is something like
so thatselect ($rout = $rbits, undef, $eout = $ebits, TIMEOUT);
$rbits
and $ebits
are never modified, with the action tests on $rout
and $eout
Re:select modifies its arguments
Abigail on 2006-10-06T12:12:56
I know, and if you look at the code, it's setting $ebits and $rbits in each iteration. $BITS is set once, and it's not modified. Just before the select loop, $ebits and $rbits are initialized with $BITS.Re:select modifies its arguments
nicholas on 2006-10-06T12:23:17
Ah OK. So I was right when I had this hunch on hitting "Submit" that I'd missed something.
:-)
Isn't there a module for this? Your mistake is in writing your own buggy code instead of using somebody's better tested module.
Re:Reinventing the wheel
Abigail on 2006-10-06T13:35:37
I've no idea whether there's a module for this. But I'm pretty sure locating the module, reading the documentation, and convincing myself the module does what I want, and is bugfree would take longer than writing and debugging a few lines myself.Re:Reinventing the wheel
BinGOs on 2006-10-06T14:11:34
Speaking of wheels, this seems an ideal candidate for a POE session and POE::Wheel::FollowTail.
Re:Reinventing the wheel
Abigail on 2006-10-06T14:46:31
Somehow it feels wrong to install a rather large selection of modules only to shave off a few lines of a less than 100 line stand alone script.shave off lines (Reinventing the wheel)
shmem on 2006-12-23T12:20:38
... specially if shaving off a few lines means writing others (probably as much as you've saved), from which at first glance you absolutely won't get what the heck they are about, and what's going on behind the scenes: that's the wrong way of abstraction.Re:Reinventing the wheel
kane on 2006-10-07T09:49:35
Yes, it is called IO::Select, released with perl 5.3.7.
Obviously, you should be doing another_thing()
in response to $p2
coming ready. I wish you wouldn't post such trivial problems.
open does not return the filehandle, so it would appear that $p1 and friends are not what you seem to expect based on the rest of the code.
Re:Can it really be that simple?
Abigail on 2006-10-06T20:21:46
While that's a mistake in the fragment I gave, I didn't make that mistake in the program.