#!./perl -w
my
$child
;
my
$can_fork
;
my
$has_perlio
;
our
%Config
;
BEGIN {
require
Config;
import
Config;
$can_fork
=
$Config
{
'd_fork'
} ||
$Config
{
'd_pseudofork'
};
if
($^O eq
"hpux"
or
$Config
{
'extensions'
} !~ /\bSocket\b/ &&
!(($^O eq
'VMS'
) &&
$Config
{d_socket})) {
print
"1..0\n"
;
exit
0;
}
}
{
if
(
$can_fork
) {
my
$parent
= $$;
$child
=
fork
;
die
"Fork failed"
unless
defined
$child
;
if
(!
$child
) {
$SIG
{INT} =
sub
{
exit
0};
my
$must_finish_by
=
time
+ 60;
my
$remaining
;
while
((
$remaining
=
$must_finish_by
-
time
) > 0) {
sleep
$remaining
;
}
warn
"Something unexpectedly hung during testing"
;
kill
"INT"
,
$parent
or
die
"Kill failed: $!"
;
if
( $^O eq
"cygwin"
) {
sleep
1;
system
(
"/bin/kill -f $parent; echo die $parent"
);
}
exit
1;
}
}
unless
(
$has_perlio
= PerlIO::Layer->can(
"find"
) && PerlIO::Layer->find(
'perlio'
)) {
print
<<EOF;
# Since you don't have perlio you might get failures with UTF-8 locales.
EOF
}
}
my
$skip_reason
;
if
( !
$Config
{d_alarm} ) {
plan
skip_all
=>
"alarm() not implemented on this platform"
;
}
elsif
( !
$can_fork
) {
plan
skip_all
=>
"fork() not implemented on this platform"
;
}
else
{
my
(
$lefth
,
$righth
);
eval
{
socketpair
$lefth
,
$righth
, -1, -1, -1};
if
($@ =~ /^Unsupported
socket
function
"socketpair"
called/ ||
$! =~ /^The operation requested is not supported./) {
plan
skip_all
=>
'No socketpair (real or emulated)'
;
}
else
{
eval
{AF_UNIX};
if
($@ =~ /^Your vendor
has
not
defined
Socket macro AF_UNIX/) {
plan
skip_all
=>
'No AF_UNIX'
;
}
else
{
plan
tests
=> 45;
}
}
}
$SIG
{ALRM} =
sub
{
die
"Unexpected alarm during testing"
};
my
@left
= (
"hello "
,
"world\n"
);
my
@right
= (
"perl "
,
"rules!"
);
my
@gripping
= (
chr
255,
chr
127);
{
my
(
$lefth
,
$righth
);
ok (
socketpair
(
$lefth
,
$righth
, AF_UNIX, SOCK_STREAM, PF_UNSPEC),
"socketpair (\$lefth, \$righth, AF_UNIX, SOCK_STREAM, PF_UNSPEC)"
)
or
print
STDERR
"# \$\! = $!\n"
;
if
(
$has_perlio
) {
binmode
(
$lefth
,
":bytes"
);
binmode
(
$righth
,
":bytes"
);
}
foreach
(
@left
) {
is (
syswrite
(
$lefth
,
$_
),
length
$_
,
"syswrite to left"
);
}
foreach
(
@right
) {
is (
syswrite
(
$righth
,
$_
),
length
$_
,
"syswrite to right"
);
}
my
(
$buffer
,
$expect
);
$expect
=
join
''
,
@right
;
undef
$buffer
;
is (
read
(
$lefth
,
$buffer
,
length
$expect
),
length
$expect
,
"read on left"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
$expect
=
join
''
,
@left
;
undef
$buffer
;
is (
read
(
$righth
,
$buffer
,
length
$expect
),
length
$expect
,
"read on right"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
ok (
shutdown
(
$lefth
, SHUT_WR),
"shutdown left for writing"
);
SKIP: {
skip
"SCO Unixware / OSR have a bug with shutdown"
,2
if
$^O =~ /^(?:svr|sco)/;
local
$SIG
{ALRM} =
sub
{
warn
"EOF on right took over 3 seconds"
};
local
$TODO
=
"Known problems with unix sockets on $^O"
if
$^O eq
'hpux'
|| $^O eq
'super-ux'
;
alarm
3;
$! = 0;
ok (
eof
$righth
,
"right is at EOF"
);
local
$TODO
=
"Known problems with unix sockets on $^O"
if
$^O eq
'unicos'
|| $^O eq
'unicosmk'
;
is ($!,
''
,
'and $! should report no error'
);
alarm
60;
}
my
$err
= $!;
$SIG
{PIPE} =
'IGNORE'
;
{
local
$SIG
{ALRM} =
sub
{
warn
"syswrite to left didn't fail within 3 seconds"
};
alarm
3;
my
$ans
=
syswrite
(
$lefth
,
"void"
);
$err
= $!;
is (
$ans
,
undef
,
"syswrite to shutdown left should fail"
);
alarm
60;
}
{
$! =
$err
;
ok (($!{EPIPE} or $!{ESHUTDOWN}),
'$! should be EPIPE or ESHUTDOWN'
)
or
printf
STDERR
"# \$\! = %d (%s)\n"
,
$err
,
$err
;
}
foreach
(
@gripping
) {
is (
syswrite
(
$righth
,
$_
),
length
$_
,
"syswrite to right"
);
}
ok (!
eof
$lefth
,
"left is not at EOF"
);
$expect
=
join
''
,
@gripping
;
undef
$buffer
;
is (
read
(
$lefth
,
$buffer
,
length
$expect
),
length
$expect
,
"read on left"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
ok (
close
$lefth
,
"close left"
);
ok (
close
$righth
,
"close right"
);
}
SKIP: {
skip
"alarm doesn't interrupt I/O on this Perl"
, 24
if
"$]"
< 5.008;
my
$success
=
socketpair
my
$lefth
,
my
$righth
, AF_UNIX, SOCK_DGRAM, PF_UNSPEC;
skip
"No useable SOCK_DGRAM for socketpair"
, 24
if
!
$success
and
($!{EAFNOSUPPORT} or $!{EOPNOTSUPP} or $!{EPROTONOSUPPORT} or $!{EPROTOTYPE});
skip
"No usable SOCK_DGRAM for socketpair"
, 24
if
($^O =~ /^(MSWin32|os2)\z/);
local
$TODO
=
"socketpair not supported on $^O"
if
$^O eq
'nto'
;
ok (
$success
,
"socketpair (\$left, \$righth, AF_UNIX, SOCK_DGRAM, PF_UNSPEC)"
)
or
print
STDERR
"# \$\! = $!\n"
;
if
(
$has_perlio
) {
binmode
(
$lefth
,
":bytes"
);
binmode
(
$righth
,
":bytes"
);
}
foreach
(
@left
) {
is (
syswrite
(
$lefth
,
$_
),
length
$_
,
"syswrite to left"
);
}
foreach
(
@right
) {
is (
syswrite
(
$righth
,
$_
),
length
$_
,
"syswrite to right"
);
}
my
(
$total
,
$buffer
);
$total
=
join
''
,
@right
;
foreach
my
$expect
(
@right
) {
undef
$buffer
;
is (
sysread
(
$lefth
,
$buffer
,
length
$total
),
length
$expect
,
"read on left"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
}
$total
=
join
''
,
@left
;
foreach
my
$expect
(
@left
) {
undef
$buffer
;
is (
sysread
(
$righth
,
$buffer
,
length
$total
),
length
$expect
,
"read on right"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
}
ok (
shutdown
(
$lefth
, 1),
"shutdown left for writing"
);
SKIP: {
skip
"$^O does length 0 udp reads"
, 2
if
($^O eq
'os390'
);
my
$alarmed
= 0;
local
$SIG
{ALRM} =
sub
{
$alarmed
= 1; };
print
"# Approximate forever as 3 seconds. Wait 'forever'...\n"
;
alarm
3;
undef
$buffer
;
is (
sysread
(
$righth
,
$buffer
, 1),
undef
,
"read on right should be interrupted"
);
is (
$alarmed
, 1,
"alarm should have fired"
);
}
alarm
30;
foreach
(
@gripping
) {
is (
syswrite
(
$righth
,
$_
),
length
$_
,
"syswrite to right"
);
}
$total
=
join
''
,
@gripping
;
foreach
my
$expect
(
@gripping
) {
undef
$buffer
;
is (
sysread
(
$lefth
,
$buffer
,
length
$total
),
length
$expect
,
"read on left"
);
is (
$buffer
,
$expect
,
"content what we expected?"
);
}
ok (
close
$lefth
,
"close left"
);
ok (
close
$righth
,
"close right"
);
}
kill
"INT"
,
$child
or
warn
"Failed to kill child process $child: $!"
;
exit
0;