(jcwren) Re: Timeout problem using IO::Socket
by jcwren (Prior) on Sep 27, 2000 at 15:40 UTC
|
You shouldn't need a timeout on the connect, but rather, on any reads (and possibly writes) to/from the socket. Here's an example of some code that I recently used that makes use of the alarm() handler.
It does not check the result of the signal handler, but suffices to know that the signal handler fired, and broke out of the eval(), which is waiting for a response on the open socket. (In this case of the code, all I need to know is that the remote host sent something (anything), to indicate it received the packet I sent it. It's not extremely robust code, but it served my purposes for playing a .WAV file to a remote Windows-running PC).
sub play_remote_file
{
my $file = shift;
my $sock = new IO::Socket::INET (PeerAddr => 'jcwren',
PeerPort => 10666,
Proto => 'tcp',
);
return unless $sock;
print $sock $file, "\n";
$SIG{ALRM} = \&timed_out;
eval {
alarm (30);
my $buf = <$sock>;
alarm (0);
};
close ($sock);
}
sub timed_out
{
die "GOT TIRED OF WAITING";
}
--Chris
e-mail jcwren | [reply] [d/l] |
|
|
Yes, I see that, but what would happen if
you called this code with a valid,unreachable
IP address (e.g. 127.0.0.2) ?
My problem is that my program hangs at the connect,
and I want that forced out...
I know IO::Socket::new times out pretty quickly when
the remeote system's port I want to reach is closed,
but I find it hanging when the system does not respond
at all.
GrtZ!,
| [reply] |
Re (tilly) 1: Timeout problem using IO::Socket
by tilly (Archbishop) on Sep 27, 2000 at 17:37 UTC
|
What OS are you using?
I think you are hitting a bug in Perl. I believe that Tom
May nailed it. I think that it has been "fixed" for some definition of fixed, but judging from this the fix is probably not going to make you happy. The actual patch is here. Judging from that you need IO::Select available with a "blocking" method to do timeouts properly.
I don't have time to pursue this further, but I think that anyone who wants to get their hands dirty with Perl is likely to find getting blocking working on your platform to be a good place to get your feet wet. | [reply] |
(jcwren) RE: Timeout problem using IO::Socket
by jcwren (Prior) on Sep 27, 2000 at 17:37 UTC
|
Here's a version that times out on opening failures. I'm still not clear where your actual concern is, since (on my machine) opening the socket times out after 5 seconds or so, in any case. By the way, if I ping 127.0.0.x on my machines, I get a reply, and connecting to a non-existant socket returns an immediate error. I had to attempt to connect to an IP address that I *knew* didn't exist to get the timeout to occur, and set a fairly short timeout.
The reason we (I) have to use a variable and not $@ (see perldoc -f eval), is because apparently IO::Socket sets up it's own eval() statement, and $@ never gets set. I had a version of code where the die() returned a string, and I found that although the die() was executing (determined by a print statement), $@ was not being returned correctly. Perhaps someone more enlightened than I can explain this (it's at the bottom of the node). I'm using 5.005-63 at work, and can't get to my machine at home to try it on 5.005_03.
#!/usr/local/bin/perl -w
use strict;
use IO::Socket;
{
my $timeout = 0;
my $sock = undef;
$SIG{ALRM} = sub {$timeout = 1; die};
eval {
alarm (2);
$sock = new IO::Socket::INET (PeerAddr => '10.1.1.18',
PeerPort => 29,
);
alarm (0);
};
die "Can't open socket: timeout=$timeout\n" if ($timeout or !$sock)
+;
print "I would print to the socket now, if I knew what I was connec
+ted to\n";
close ($sock);
}
#!/usr/local/bin/perl -w
use strict;
use IO::Socket;
{
my $sock = undef;
$SIG{ALRM} = sub {die "GOT TIRED OF WAITING"};
eval {
alarm (2);
$sock = new IO::Socket::INET (PeerAddr => '10.0.0.18',
PeerPort => 29,
);
alarm (0);
};
die "Can't open socket: $@\n" if (!$sock);
print "I would print to the socket now, if I knew what I was connec
+ted to\n";
close ($sock);
}
--Chris
e-mail jcwren | [reply] [d/l] [select] |
Re: Timeout problem using IO::Socket
by ChOas (Curate) on Sep 27, 2000 at 16:14 UTC
|
Just a quick example, I want this to time out On MY conditions
when no connection can be set up to the entered IP address,believe me, there were a LOT of alarms, evals, etc. in here ;))
#!/usr/bin/perl -w
use strict;
use IO::Socket;
die "Usage: <IP address> <Port>\n" unless (scalar @ARGV==2);
my $Status="Failed";
my ($Host,$Port)=@ARGV;
my $Socket=IO::Socket::INET->new("$Host:$Port");
$Status="Okay" if $Socket;
die "Everything $Status\n";
| [reply] [d/l] |
Re: Timeout problem using IO::Socket
by lhoward (Vicar) on Sep 27, 2000 at 16:44 UTC
|
I know this doesn't really address your problem directly, but....
Have you considered pinging (Net::Ping) the host first to make sure it is alive
before you enter the IO::Socket section of your code? It may
be much easier than handling the connection timeout the way you
want to. | [reply] |
|
|
| [reply] [d/l] |
Re: Timeout problem using IO::Socket
by BastardOperator (Monk) on Sep 27, 2000 at 16:53 UTC
|
You know you've been programming to long when your debugging lines contain swear words
shoot, that's just the intermediate stage, you'll have prayers in your code when you've really been programming too long :).
i.e. "Oh lord, who art in heaven, please make this code work, aaaammmmmeeennnn"
| [reply] |
(tye)Re: Timeout problem using IO::Socket
by tye (Sage) on Sep 27, 2000 at 17:51 UTC
|
Hubris time here. I think everyone has missed the problem. If
your program is printing "Alarm Clock" then you haven't
set up your $SIG{ALRM} handler correctly. You didn't show
us that part of the code. "Alarm Clock" is what is printed
by the default handler for SIGALRM.
-
tye
(but my friends call me "Tye")
| [reply] |
Re: Timeout problem using IO::Socket
by ChOas (Curate) on Sep 27, 2000 at 18:18 UTC
|
*grin*, Don't you guys love this problem ? :)))
I just checked jcwrens option ... can anyone tell
me this is the way to set up an alarm handler ?..
'coz it for sure prints 'Alarm Clock' for me ;))
montest@XXX-test$ ./test 127.0.0.1
I would print to the socket now, if I knew what I was connected to
montest@XXX-test$ ./test 127.0.0.2
Alarm Clock
montest@XXX-test$
Any Ideas ?.. btw.. thank you all for helping me out here
update
Oh, I usually set my alarm handler this way:
$SIG{ALRM}=\&AlarmHandler;
| [reply] [d/l] |
|
|
How about setting your alarm more directly, for
more accurate debugging -
$SIG{ALRM} = sub { die "DIE DIE DIE!\n" };
Show us the actual excerpt of your code -- you're
asking us to use our imaginations in dreaming up
possibilities for what is obviously a subtle problem.
| [reply] [d/l] |
|
|
$SIG{ALRM}=\&AlarmHandler;
Well, that looks right as far as it goes. But if your program
is printing "Alarm Clock" and then dieing, then you almost
certainly are not setting up your alarm handler properly. Perhaps
you are doing this too late, undoing it too early, have it
in some conditional that you think is being run but isn't,
etc. Perhaps some other code is setting up its own alarm
handler and overwriting yours. You might want to step through
this with the Perl debugger.
-
tye
(but my friends call me "Tye")
| [reply] |
RE: Timeout problem using IO::Socket
by lolindrath (Scribe) on Sep 27, 2000 at 22:15 UTC
|
Greetings,
I was interested in the this sig handler problem so I found a simple example in my book and wrote it up. Well, it worked fine under linux but Windows doesn't seem to like the alarm function. Just wanted to note this quick compatibility problem.
--=Lolindrath=-- | [reply] |
Re: Timeout problem using IO::Socket
by ChOas (Curate) on Sep 28, 2000 at 13:19 UTC
|
Okay...
It must be perl... code works on an IBM RS6000
running AIX 4.3, perl version 5.005_03 .
I should have checked every system first for
incompatibilities before asking questions here
I'll just have to find a way around this, or get management
to upgrade Perl on all our platforms (can you spell 'Hell' ? :))
I'm sorry guys, thank you all so much for your help.
| [reply] |
Re: Timeout problem using IO::Socket
by ChOas (Curate) on Sep 28, 2000 at 11:46 UTC
|
Hmmmmm maybe I should have mentioned this earlier
I found this in Socket.pm:
local($SIG{ALRM}) = $timeout ? sub { undef $fh; }
: $SIG{ALRM} || 'DEFAULT';
Still... There is no reason why MY alarm handler (defined)
was/is overwritten
Eeehm, as for original code...: The code jcwren
posted above gives me the same results, and it's
pretty clear code...
Has anyone else tried his code ?
Oh, I'm running on a sun sparc ultra4, SunOs 5.6,
Perl 5.004_04...
Code from jcwren gives me the same 'Alarm Clock' on
RH Linux 2.0.36, i386, also Perl 5.004_04
| [reply] [d/l] |