php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #31894 Calling restore_error_handler inside destructor crashes PHP
Submitted: 2005-02-09 12:24 UTC Modified: 2005-02-28 01:00 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: adove at mindrage dot com Assigned:
Status: No Feedback Package: Scripting Engine problem
PHP Version: 5.0.3 OS: WinXP
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: adove at mindrage dot com
New email:
PHP Version: OS:

 

 [2005-02-09 12:24 UTC] adove at mindrage dot com
Description:
------------
This may be related to an older bug that was fixed (#24708) but I can reproduce reliably (having spent days and hours chasing!). Basically, if you call restore_error_handler from __destruct() things go horribly ary. Interestingly enough, calling restore_exception_handler works just fine.

This happens both CLI and Apache 2.x. 

Note that it does not matter if you use $this or &$this in the constructor. 

Reproduce code:
---------------
    function __construct(
        &$aConfig
        )
    {
        if(is_array($aConfig))
        {
            $this->m_aConfig = &$aConfig; // Extraneous but it's in my constructor.
            set_error_handler(array &$this, "handleRuntimeException"));
            set_exception_handler(array($this, "handleException"));
        }
    }
        
    function __destruct()
    {
        //restore_error_handler();
        restore_exception_handler();
        unset($this->m_aConfig);
    }



Expected result:
----------------
Proper ending of PHP script execution. 

Actual result:
--------------
Segfault in php5ts.dll, ModVer: 5.0.3.3 Offset: 0004d661

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-02-09 23:44 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.

Also, please try CVS snapshot first - I can't reproduce it with the parts of the code you've posted.
 [2005-02-28 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2006-08-02 11:13 UTC] f dot boender at electricmonk dot nl
I'm experiencing the same bug. Here's my bugreport:

Description:
------------

    PHP crashes with a segmentation fault when restoring the error handler in
    the destructor. 

Environment:
------------
    
    PHP: 
        PHP 5.1.2-1+b1 (cli) (built: Mar 20 2006 04:17:24)
        Copyright (c) 1997-2006 The PHP Group
        Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
    
    php.ini excerpt:
        error_reporting  =  E_ALL & ~E_NOTICE & ~E_STRICT
        display_errors = On
        display_startup_errors = Off
        log_errors = Off
        log_errors_max_len = 1024
        ignore_repeated_errors = Off
        track_errors = Off

Observations:
-------------

    * The test program crashes with a segfault when run as shown here.
    * The test program does NOT crash when the destructor is called due to
      the instance of Test going out of scope. (Comment out the OUT-OF-SCOPE
      piece). Not even the unset() crashes after the OUT-OF-SCOPE test has
      run first.
    
Test program:
-------------

    <?php
    
    class Test {
    	private $prevErrorReporting = 0;
    
    	public function __construct() {
    		$this->prevErrorReporting = error_reporting(E_ALL);
    		set_error_handler(array(&$this, "errorHandler"));
    	}
    
    	public function __destruct() {
    		restore_error_handler();
    		error_reporting($this->prevErrorReporting);
    		echo("trace1");
    	}
    
    	public function errorHandler($errno, $errmsg, $filename, $linenum, $vars) {
    	}
    }
    
    // OUT-OF-SCOPE TEST
    // { 
    // $test = new Test();
    // }
    
    // UNSET TEST
    $test = new Test();
    unset($test); // Unsetting, destructor is called, SegFault (unless OUT-OF-SCOPE test has run)
    
    ?>

Expected output:
----------------

    [todsah@jib]~/dev/tlib-php$ export MALLOC_CHECK_=1
    [todsah@jib]~/dev/tlib-php$ php ./tlib-test.php 
    malloc: using debugging hooks
    trace1

Actual output:
--------------

    [todsah@jib]~/dev/tlib-php$ export MALLOC_CHECK_=1
    [todsah@jib]~/dev/tlib-php$ php ./tlib-test.php 
    malloc: using debugging hooks
    Segmentation fault

GDB output:
-----------
  
    Here's some output from GDB; might be useful. Duplicate lines and default
    GDB messages have been removed.
    
    > (gdb) run
    > Starting program: /usr/bin/php tlib-test.php
    > malloc: using debugging hooks
    > 
    > Program received signal SIGSEGV, Segmentation fault.
    > 0x08298316 in zend_std_read_property ()
    > (gdb) 

Strace output:
--------------

    Useless probably, but anyway:
    
    > rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0
    > ioctl(5, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf86e0d8) = -1 ENOTTY (Inappropriate ioctl for device)
    > read(5, "<?php\n\nclass Test {\n\tprivate $pr"..., 8192) = 560
    > read(5, "", 4096)                       = 0
    > read(5, "", 8192)                       = 0
    > close(5)                                = 0
    > munmap(0xb78ad000, 4096)                = 0
    > --- SIGSEGV (Segmentation fault) @ 0 (0) ---
    > +++ killed by SIGSEGV +++
    > Process 5638 detached
 [2006-08-02 11:27 UTC] f dot boender at electricmonk dot nl
I've succesfully reproduced the Segmentation fault of the above test program on the following systems: (All Debian GNU/Linux systems);

Commandline:
    PHP 5.0.5-Debian-0.8~sarge1 (cli) (built: Oct 27 2005
    10:43:05) (Debian GNU/Linux) Copyright (c) 1997-2004
    The PHP Group

Commandline:
    PHP 5.0.4-0.9sarge1 (cli) (built: Jul 20 2005 17:08:52)
    (Debian GNU/Linux) Copyright (c) 1997-2004 The PHP
    Group Zend Engine v2.0.4-dev, Copyright (c) 1998-2004
    Zend Technologies

Apache module:

    PHP Version 5.1.2-1+b1
    System = Linux jib 2.6.15.5 #2  i686
    Build Date = Mar 20 2006 04:04:37
    Server API = Apache 2.0 Handler
    Virtual Directory Support = disabled
    PHP API = 20041225
    PHP Extension = 20050922
    Zend Extension = 220051025
 [2006-08-02 11:56 UTC] f dot boender at electricmonk dot nl
Oops, small correction on the test program in my first comment. It turns out {} doesn't actually represent a new scope at all. It's the redefining of $test that causes the destructor of the previous $test to get triggered instead of going out of scope. Same results though.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 20:01:29 2024 UTC