develooper Front page | perl.perl5.porters | Postings from November 2010

Re: [perl #75556] segfault in PerlIOBuf_fill when filehandle isclosed in a signal handler

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
November 26, 2010 09:59
Subject:
Re: [perl #75556] segfault in PerlIOBuf_fill when filehandle isclosed in a signal handler
Message ID:
20101126161118.GA2685@iabyn.com
On Sun, Jul 25, 2010 at 01:02:01PM -0700, Father Chrysostomos wrote:
> > PerlIOUnix_read has a loop which makes a blocking read, and calls
> > PERL_ASYNC_CHECK() if the read is interrupted by a signal.
> > 
> > Once PERL_ASYNC_CHECK() has returned, the pointers "f" and "buf"
> > in PerlIOUnix_read are pointing to freed space, which looks fairly
> > simple to detect and handle. Similar bugs also need fixing
> > elsewhere in perlio.c.
> 
> I don’t know a lot about C, but I think that the freed memory could be
> re-used for something else, in which case checking that it has been
> freed (how do you do that, BTW?) will not be reliable. (Someone please
> correct me if I’m wrong.) Maybe we need some sort of refcounting
> mechanism for PerlIOl’s. How much of the PerlIO API is public?

Now fixed (sort-of) by the following set of commits:

    303f2dc3d5bda8ee962db318dd53acb167c07485
    16865ff7e97c2532fd2001d68cf18909acb0d838
    8995e67d43b457d0463f0581e10b390bc378c894
    cc6623a84b782d30463b9046c2916f35064a7e3f
    abf9167d3fff002ddaed53abb44d638387bca978

but most specifically by that last one:

commit abf9167d3fff002ddaed53abb44d638387bca978
Author:     David Mitchell <davem@iabyn.com>
AuthorDate: Mon Nov 22 19:18:49 2010 +0000
Commit:     David Mitchell <davem@iabyn.com>
CommitDate: Fri Nov 26 16:01:34 2010 +0000

    Make PerlIO marginally reentrant
    
    Currently if an operation on a file handle is interrupted, and if
    the signal handler accesses that same file handle (e.g. closes it),
    then perl will crash. See [perl #75556].
    
    This commit provides some basic infrastructure to avoid segfaults.
    Basically it adds a lock count field to each handle (by re-purposing the
    unused flags field in the PL_perlio array), then each time a signal
    handler is called, the count is incremented. Then various parts of PerlIO
    use a positive count to change behaviour. Most importantly, when layers
    are popped, the PerlIOl structure is cleared, but not freed, and is left
    in the chain of layers. This means that callers still holding pointers to
    the various layers won't access freed structures. It does however mean
    that PerlIOl structs may be leaked, and possibly slots in PL_perlio. But
    this is better than crashing.
    
    Not much has been done to give sensible behaviour on re-entrancy; for
    example, a buffer that has already been written once might get written
    again. Fixing this sort of thing would require a large-scale audit of
    perlio.c.


Note that the glib fread() function crashes if you call fclose() in a
signal-handler, so we're better than that now :-)

-- 
"The GPL violates the U.S. Constitution, together with copyright,
antitrust and export control laws"
    -- SCO smoking crack again.

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