Socket creation failing with "operation now in progress" error

G

google

I am attempting to establish a socket connection using the
IO::Socket::INET module and occasionally the socket creation fails
with the message "Operation now in progress". From what I understand,
this error can only happen when attempting to create a socket in non-
blocking mode, never in blocking mode. However, I have explicitly set
the Blocking parameter to 1.

So, my question is: what could be causing this error? Does
IO::Socket::INET ignore the Blocking parameter?

The OS is 64-bit Redhat Enterprise Linux 4; the version of perl is
5.8.5; the IO::Socket::INET is version 1.27.

Here is the portion of code where the problem happens
########################
$socket = new IO::Socket::INET(
PeerAddr => my.ip.address.com,
PeerPort => 5000,
Proto => 'tcp',
Type => SOCK_STREAM,
Timeout => 30,
Blocking => 1,
) ;
}

# Did the socket get created correctly?
if (!$socket)
{
LogError("Socket to $IP could not be created. "
. "Reason: $!") ;
exit
}
##########################
 
X

xhoster

I am attempting to establish a socket connection using the
IO::Socket::INET module and occasionally the socket creation fails
with the message "Operation now in progress". From what I understand,
this error can only happen when attempting to create a socket in non-
blocking mode, never in blocking mode. However, I have explicitly set
the Blocking parameter to 1.

What is in "$@"? That may be a better error message than the one in $!.
# Did the socket get created correctly?
if (!$socket)
{
LogError("Socket to $IP could not be created. "
. "Reason: $!") ;
exit
}
##########################

Xho
 
G

google

What is in "$@"? That may be a better error message than the one in $!.

The $@ string is empty; the only error information comes from $!.
Isn't $@ only set after an eval? I do not use an eval in my code.
 
B

Brian McCauley

I am attempting to establish a socket connection using the
IO::Socket::INET module and occasionally the socket creation fails
with the message "Operation now in progress". From what I understand,
this error can only happen when attempting to create a socket in non-
blocking mode, never in blocking mode. However, I have explicitly set
the Blocking parameter to 1.
Timeout => 30,
Blocking => 1,

But you also set the timeout parameter, which is another form of non-
blocking, and it in fact implemented by putting the socket temporarily
into non-blocking mode.
 
X

xhoster

The $@ string is empty;

I didn't expect that. Usually IO::Socket::INET will at least copy "$!"
into $@ if it can't think of a better error message to stick there.
the only error information comes from $!.
Isn't $@ only set after an eval? I do not use an eval in my code.

It is automatically used for evals, but modules are also free to manually
use it as they feel fit. Modules can make many system calls on your behalf
before they give up, and the error message set in $! by the last one to
fail may not be the most relevant error message, and there may be valuable
context that is not provided by $!. So a module may set $@ to give you a
"big picture" of the error, rather than the small picture that is in $!.

I'd put something like this after the "use IO::Socket::INET" to try to
track down the path that the error takes:

{ package IO::Socket::INET;
use Data::Dumper;
use Carp;
sub _error { confess Dumper(\@_), ":" }
};

Xho
 
X

xhoster

Brian McCauley said:
But you also set the timeout parameter, which is another form of non-
blocking, and it in fact implemented by putting the socket temporarily
into non-blocking mode.

I would expect it to return a better error message in $@ in this case. I
don't see what path is being taken that doesn't result in a better error
message in that variable.

Xho
 
B

Brian McCauley

I would expect it to return a better error message in $@ in this case. I
don't see what path is being taken that doesn't result in a better error
message in that variable.

Nor do I.


$blocking = $sock->blocking(0) if $timeout;
if (!connect($sock, $addr)) {
if (defined $timeout && $!{EINPROGRESS}) {
require IO::Select;

my $sel = new IO::Select $sock;

if (!$sel->can_write($timeout)) {
$err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
$@ = "connect: timeout";
}
elsif (!connect($sock,$addr) && not $!{EISCONN}) {
# Some systems refuse to re-connect() to
# an already open socket and set errno to EISCONN.
$err = $!;
$@ = "connect: $!";
}
}
elsif ($blocking || !$!{EINPROGRESS}) {
$err = $!;
$@ = "connect: $!";
}
}

And the only path that ends up with $!=EINPROGRESS is if the select()
reports that the socket is if the IO::Select object's can_write
returns true then the connection drops again before the second
connect(). There should be a better way of checking the status of the
socket when can_write returns true rather than retrying the
connect().

Actually it's unclear why that second connect is there at all, AFAIK
the fact that can_write() was true should be indication enough that
the connection succeeded. If the connection was immediately dropped
then the next operation on the socket should error.
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top