Is this also the case for syswrite in Perl, or does Perl take care of that
for us? In other words, do I actually need code like the following:
# It's possible for write(2) to return a fewer number of written
# bytes than the size of the buffer being written. To allow for
# that, we need to keep writing until either the entire buffer has
# been written or we get an error of some sort. Because the socket
# is non-blocking, we also need to select on it to make sure that
# it's ready for data.
do {
my $win = '';
my $wout;
vec ($win, $self->{fh}->fileno, 1) = 1;
my $nbits = select (undef, $wout = $win, undef, $TIMEOUT);
if ($nbits < 1) { return undef }
# Actually write out the data.
$written = syswrite ($self->{fh}, $$buf, (length $$buf) - $count,
$count);
unless ($written) {
$self->shutdown;
return undef;
}
$count += $written;
} until ($count == length $$buf);
or am I going to far too much work? (Note that the above code is writing
to a *non-blocking* socket, which changes the situation somewhat.)
Peering at the LWP::* modules, all of those routines seem to push this
problem off on the user by returning the number of bytes that syswrite
returned.
(And yes, I'm reimplementing low-level socket I/O rather than using
LWP::*. Yes, I'd rather use LWP::*, all things being equal, but I
specifically don't want this module to depend on any modules which aren't
in Perl core and I don't need the entire baggage of LWP. Besides, it only
took a couple of hours to write, and it was fun.)
--
Russ Allbery (r...@cs.stanford.edu) <URL:http://www.eyrie.org/~eagle/>
In comp.lang.perl.misc,
Russ Allbery <r...@cs.stanford.edu> writes:
:One of the annoyances about the standard write(2) system call is that
:under some circumstances it is possible for a successful write to write
:fewer than the total number of requested bytes. It's therefore necessary
:in C to check the return value of write(2) and repeat as necessary until
:all of the data has been written.
:
:Is this also the case for syswrite in Perl, or does Perl take care of that
:for us? In other words, do I actually need code like the following:
[elision for the sake of wit's soul]
:or am I going to far too much work? (Note that the above code is writing
:to a *non-blocking* socket, which changes the situation somewhat.)
:
:Peering at the LWP::* modules, all of those routines seem to push this
:problem off on the user by returning the number of bytes that syswrite
:returned.
Use the Source, Russ:-)
PP(pp_syswrite)
{
return pp_send(ARGS);
}
PP(pp_send)
{
dSP; dMARK; dORIGMARK; dTARGET;
GV *gv;
IO *io;
int offset;
SV *bufsv;
char *buffer;
int length;
STRLEN blen;
gv = (GV*)*++MARK;
if (!gv)
goto say_undef;
bufsv = *++MARK;
buffer = SvPV(bufsv, blen);
length = SvIVx(*++MARK);
if (length < 0)
DIE("Negative length");
SETERRNO(0,0);
io = GvIO(gv);
if (!io || !IoIFP(io)) {
length = -1;
if (dowarn) {
if (op->op_type == OP_SYSWRITE)
warn("Syswrite on closed filehandle");
else
warn("Send on closed socket");
}
}
else if (op->op_type == OP_SYSWRITE) {
if (MARK < SP)
offset = SvIVx(*++MARK);
else
offset = 0;
if (length > blen - offset)
length = blen - offset;
length = write(PerlIO_fileno(IoIFP(io)), buffer+offset, length);
}
#ifdef HAS_SOCKET
else if (SP > MARK) {
char *sockbuf;
STRLEN mlen;
sockbuf = SvPVx(*++MARK, mlen);
length = sendto(PerlIO_fileno(IoIFP(io)), buffer, blen, length,
(struct sockaddr *)sockbuf, mlen);
}
else
length = send(PerlIO_fileno(IoIFP(io)), buffer, blen, length);
#else
else
DIE(no_sock_func, "send");
#endif
if (length < 0)
goto say_undef;
SP = ORIGMARK;
PUSHi(length);
RETURN;
say_undef:
SP = ORIGMARK;
RETPUSHUNDEF;
}
So, yes, you have to worry about it. Here's one example:
#!/usr/bin/perl
# cpfiles -- copy files paranoically
# tch...@perl.com
$DEFSIZE = 16 * 2**10;
($src, $dst) = @ARGV;
die "usage: $0 oldfile newfile\n" unless @ARGV == 2;
die "no source file $src: $!" unless -e $src;
die "dest file $dst exists" if -e $dst || -l $dst;
open(SRC, "< $src") || die "can't open $src: $!";
open(DST, "> $dst") || die "can't open $dst: $!";
$bsize = (stat(SRC))[11];
$bsize = $DEFSIZE unless $bsize > $DEFSIZE;
while ($readcount = sysread(SRC, $buffer, $bsize)) {
for ($offset = 0;
$offset < length($buffer);
$offset += $writecount
)
{
$writecount = syswrite(DST, $buffer, length($buffer), $offset);
die "syswrite on $dst failed: $!" unless defined $writecount;
}
}
die "sysread on $src failed: $!" unless defined $readcount;
close(SRC) || die "can't close $src: $!";
close(DST) || die "can't close $dst: $!";
Does anyone else see the bug that I see? Hint: The code was
written back before I could address it, but now I could.
--tom
--
Tom Christiansen Perl Consultant, Gamer, Hiker tch...@mox.perl.com
: I've heard that there is a shell (bourne or csh) to perl filter, does
: anyone know of this or where I can get it?
Yeah, you filter it through Tom Christiansen. :-) --Larry Wall