forked from schacon/perl
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rt.cpan.org #61577] sockdomain and socktype undef on newly accepted …
…sockets There appears to be a flaw in IO::Socket where some IO::Socket objects are unable to properly report their socktype, sockdomain, or protocol (they return undef, even when the underlying socket is sufficiently initialized to have these properties). The attached patch should cover IO::Socket objects created via accept(), new_from_fd(), new(), and anywhere else whose details haven't been properly cached. No new code should be executed on IO::Socket objects whose details are already cached and present. These tests were original written by Daniel Kahn Gillmor <dkg@fifthhorseman.net>, I've mangled them for use in a hopefully final fix for the issue.
- Loading branch information
Showing
5 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#!/usr/bin/perl | ||
|
||
use warnings; | ||
use strict; | ||
|
||
use IO::Socket; | ||
use IO::Socket::INET; | ||
use Socket; | ||
use Test::More; | ||
use Config; | ||
|
||
plan tests => 8; | ||
|
||
my $listener = IO::Socket::INET->new(Listen => 1, | ||
LocalAddr => '127.0.0.1', | ||
Proto => 'tcp'); | ||
ok(defined($listener), 'socket created'); | ||
|
||
my $port = $listener->sockport(); | ||
|
||
my $p = $listener->protocol(); | ||
ok(defined($p), 'protocol defined'); | ||
my $d = $listener->sockdomain(); | ||
ok(defined($d), 'domain defined'); | ||
my $s = $listener->socktype(); | ||
ok(defined($s), 'type defined'); | ||
|
||
SKIP: { | ||
skip "fork not available", 4 | ||
unless $Config{d_fork} || $Config{d_pseudofork}; | ||
|
||
my $cpid = fork(); | ||
if (0 == $cpid) { | ||
# the child: | ||
sleep(1); | ||
my $connector = IO::Socket::INET->new(PeerAddr => '127.0.0.1', | ||
PeerPort => $port, | ||
Proto => 'tcp'); | ||
exit(0); | ||
} else {; | ||
ok(defined($cpid), 'spawned a child'); | ||
} | ||
|
||
my $new = $listener->accept(); | ||
|
||
local $TODO = "this information isn't cached for accepted sockets"; | ||
is($new->sockdomain(), $d, 'domain match'); | ||
SKIP: { | ||
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); | ||
is($new->protocol(), $p, 'protocol match'); | ||
} | ||
SKIP: { | ||
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); | ||
is($new->socktype(), $s, 'type match'); | ||
} | ||
|
||
wait(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#!/usr/bin/perl | ||
|
||
use warnings; | ||
use strict; | ||
|
||
use IO::Socket; | ||
use IO::Socket::INET; | ||
use Socket; | ||
use Test::More; | ||
|
||
plan tests => 7; | ||
|
||
my $listener = IO::Socket::INET->new(LocalAddr => '127.0.0.1', | ||
Proto => 'udp'); | ||
ok(defined($listener), 'socket created'); | ||
|
||
my $p = $listener->protocol(); | ||
ok(defined($p), 'protocol defined'); | ||
my $d = $listener->sockdomain(); | ||
ok(defined($d), 'domain defined'); | ||
my $s = $listener->socktype(); | ||
ok(defined($s), 'type defined'); | ||
|
||
my $new = IO::Socket::INET->new_from_fd($listener->fileno(), 'r+'); | ||
|
||
local $TODO = "this information isn't cached for accepted sockets"; | ||
is($new->sockdomain(), $d, 'domain match'); | ||
SKIP: { | ||
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); | ||
is($new->protocol(), $p, 'protocol match'); | ||
} | ||
SKIP: { | ||
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); | ||
is($new->socktype(), $s, 'type match'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#!/usr/bin/perl | ||
|
||
use warnings; | ||
use strict; | ||
|
||
use File::Temp qw(tempdir); | ||
use File::Spec::Functions; | ||
use IO::Socket; | ||
use IO::Socket::UNIX; | ||
use Socket; | ||
use Config; | ||
use Test::More; | ||
|
||
plan skip_all => "UNIX domain sockets not implemented on $^O" | ||
if ($^O =~ m/^(?:qnx|nto|vos|MSWin32)$/); | ||
|
||
plan tests => 15; | ||
|
||
my $socketpath = catfile(tempdir( CLEANUP => 1 ), 'testsock'); | ||
|
||
# start testing stream sockets: | ||
my $listener = IO::Socket::UNIX->new(Type => SOCK_STREAM, | ||
Listen => 1, | ||
Local => $socketpath); | ||
ok(defined($listener), 'stream socket created'); | ||
|
||
my $p = $listener->protocol(); | ||
ok(defined($p), 'protocol defined'); | ||
my $d = $listener->sockdomain(); | ||
ok(defined($d), 'domain defined'); | ||
my $s = $listener->socktype(); | ||
ok(defined($s), 'type defined'); | ||
|
||
SKIP: { | ||
skip "fork not available", 4 | ||
unless $Config{d_fork} || $Config{d_pseudofork}; | ||
|
||
my $cpid = fork(); | ||
if (0 == $cpid) { | ||
# the child: | ||
sleep(1); | ||
my $connector = IO::Socket::UNIX->new(Peer => $socketpath); | ||
exit(0); | ||
} else { | ||
ok(defined($cpid), 'spawned a child'); | ||
} | ||
|
||
my $new = $listener->accept(); | ||
|
||
$TODO = "this information isn't cached for accepted sockets"; | ||
is($new->sockdomain(), $d, 'domain match'); | ||
SKIP: { | ||
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); | ||
is($new->protocol(), $p, 'protocol match'); | ||
} | ||
SKIP: { | ||
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); | ||
is($new->socktype(), $s, 'type match'); | ||
} | ||
|
||
unlink($socketpath); | ||
wait(); | ||
} | ||
|
||
undef $TODO; | ||
# now test datagram sockets: | ||
$listener = IO::Socket::UNIX->new(Type => SOCK_DGRAM, | ||
Local => $socketpath); | ||
ok(defined($listener), 'datagram socket created'); | ||
|
||
$p = $listener->protocol(); | ||
ok(defined($p), 'protocol defined'); | ||
$d = $listener->sockdomain(); | ||
ok(defined($d), 'domain defined'); | ||
$s = $listener->socktype(); | ||
ok(defined($s), 'type defined'); | ||
|
||
my $new = IO::Socket::UNIX->new_from_fd($listener->fileno(), 'r+'); | ||
|
||
$TODO = "this information isn't cached for new_from_fd sockets"; | ||
is($new->sockdomain(), $d, 'domain match'); | ||
SKIP: { | ||
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); | ||
is($new->protocol(), $p, 'protocol match'); | ||
} | ||
SKIP: { | ||
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); | ||
is($new->socktype(), $s, 'type match'); | ||
} | ||
unlink($socketpath); |