$err ? undef : $sock;
}
+# Enable/disable blocking IO on sockets.
+# Without args return the current status of blocking,
+# with args change the mode as appropriate, returning the
+# old setting, or in case of error during the mode change
+# undef.
sub blocking {
my $sock = shift;
# Windows handles blocking differently
#
- # http://groups.google.co.uk/group/perl.perl5.porters/browse_thread/
- # thread/b4e2b1d88280ddff/630b667a66e3509f?#630b667a66e3509f
- # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
- # winsock/winsock/ioctlsocket_2.asp
+ # http://groups.google.co.uk/group/perl.perl5.porters/browse_thread/thread/b4e2b1d88280ddff/630b667a66e3509f?#630b667a66e3509f
+ # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ioctlsocket_2.asp
#
# 0x8004667e is FIONBIO
- # By default all sockets are blocking
-
- return !${*$sock}{io_sock_nonblocking}
- unless @_;
+ #
+ # which is used to set blocking behaviour.
- my $block = shift;
+ # NOTE:
+ # This is a little confusing, the perl keyword for this is
+ # 'blocking' but the OS level behaviour is 'non-blocking', probably
+ # because sockets are blocking by default.
+ # Therefore internally we have to reverse the semantics.
- ${*$sock}{io_sock_nonblocking} = $block ? "0" : "1";
+ my $orig= !${*$sock}{io_sock_nonblocking};
+
+ return $orig unless @_;
- return ioctl($sock, 0x8004667e, \${*$sock}{io_sock_nonblocking});
+ my $block = shift;
+
+ if ( !$block != !$orig ) {
+ ${*$sock}{io_sock_nonblocking} = $block ? 0 : 1;
+ ioctl($sock, 0x8004667e, pack("L!",${*$sock}{io_sock_nonblocking}))
+ or return undef;
+ }
+
+ return $orig;
}