develooper Front page | perl.perl5.porters | Postings from February 2003

Re: Smoke [5.9.0] 18609 FAIL(F) MSWin32 5.1 (x86/1 cpu)

Thread Previous | Thread Next
From:
Enache Adrian
Date:
February 1, 2003 10:53
Subject:
Re: Smoke [5.9.0] 18609 FAIL(F) MSWin32 5.1 (x86/1 cpu)
Message ID:
20030201185958.GA1243@ratsnest.hole
On Sat, Feb 01, 2003 at 12:51:57PM +0000, Nick Ing-Simmons wrote:
> I already said that the fstat() trick was flawed when PerlIO layers
> are involved - it would have been cool for perl5.6 but now it is 
> just going to get in the way - it at least needs changing so that 
> in SNARF mode once you have read st_size octets you re-try and see if
> there are anymore. Consider a layer which does something like 
> MIME encode what is being read - you may be gets-ing far more than 
> was on disk.
> 
> It is also not clear that the st.st_size != 0 test is sufficent - 
> pipes, sockets, FIFOs might (on some systems) have finite size.
> You need explcit test for a regular file.

That's exactly the point I missed. _Most_ systems may return a non-zero
st_size for FIFOs, pipes, etc. ( linux, BSDs, windows nowithstanding )

> The attached patch (which creates //depot/perlio/sv.c@18612) implements 
> all the above suggestions, and also avoids the "short buffered" case 
> when rslen == 0 (which should now be rare).

That' still kludgy somehow.
The most concerning point is that mix of low-level and layer-level functions. 

One may for instance write an i/o layer which has nothing to do with
file descriptors, (think some kind of 'obstack', or embedding perl into
another application) and a syscall is there just to get an EBADF.

On the other side, if that layer serves a known size object as a file,
it'll be nice to get it in one shot too when in slurp mode.

My suggestion is to add a new layer-level function 'PerlIO_size()' wired
to a 'Size' callback from the _PerlIO_funcs structure.

That will get the size of the file with fstat() where this is appropriate
( unix, cr/lf & mmapped i/o on regular files ) and will be a NULL
pointer in transforming layers (de/compressing, MIME encoding, etc).

( On transforming layers reading by big chunks will cause more grief
rather than speeding up. :_( )

This arrangement will also avoid a useless system call and will be
more flexible.

For example: (these are just suggestions)

-- perlio.c

SSize_t
Perl_PerlIO_size(pTHX_ PerlIO *f)
{
    if (PerlIOValid(f) && PerlIOBase(f)->tab->Size)
	return (*PerlIOBase(f)->tab->Size) (aTHX_ f);
    else {
	SETERRNO(EBADF, SS_IVCHAN);
	return -1;
    }
}

-- perlstdio.h - if the user sticks to non-layered i/o

#define PerlIO_size(f)	\
	(fstat(fileno(f),&PL_statbuf) || !S_ISREG(PL_statbuf.st_mode) ? \
	 0 : (Ssize_t)PL_statbuf.st_size)


The code in sv_gets() may be then rewritten as:

	if ((recsize = PerlIO_size(fp) - PerlIO_tell(fp)) > 0)
	    goto read_record;
	rsptr = NULL;
	rslen = 0;


Hoping you'll find this bloat accepting :-)
Adi

P.S.
Sorry if I messed up something. I'm not familiar with the perliol code.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About