php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68596 Included file on a register_shutdown_function() does not define it's functions
Submitted: 2014-12-12 16:58 UTC Modified: 2017-03-11 18:09 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (50.0%)
From: php at maisqi dot com Assigned: nikic (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.6.3 OS: Windows / Linux
Private report: No CVE-ID: None
 [2014-12-12 16:58 UTC] php at maisqi dot com
Description:
------------
This error only manifests in a complex scenario:
  1. A function registered with register_shutdown_function(), includes another file that defines some functions;
  2. A third file is required by the first and defines two classes with the same name, which throws a fatal error;
  3. This last file has a namespace and at least one of the classes (that share the same name) inherits from a base class;
  4. The shutdown function runs after the fatal error has occurred and includes the second file, but it's functions never make it into the global scope. That problem does not happen with classes, for example.

Note that if the third file does not have a namespace or if none of the same named classes inherit, all goes as expected: a fatal error is thrown and the shutdown function has access to the functions defined on the file it includes.

I included PHP examples for the scenario.

Test script:
---------------
<?php
/**
 * driver.php
 * ----------
 * Registers a shutdown-function, that includes "error_handler.php" (which merely defines
 * a innocuous function named "handle_error", and includes "throw_fatal_error.php"
 * (that provokes an error  declaring two classes with the same name).
 *
 * What happens is that the fatal error is thrown, shutdownFunc() is called and
 * "error_handler.php" is included -- but it occurs another fatal error, complaining that
 * handle_error() (defined in "error_handler.php") is undefined.
 * The problem does not happen with classes, as can be demonstrated by ErrorClass,
 * which is defined in "error_handler.php" and it's existence checked on shutdownFunc().
 *
 * VERY IMPORTANT NOTE
 *   If "throw_fatal_error.php" does not include a namespace or if neither class inherits
 *   from another, everything works ok!
 */
function shutdownFunc () {
	require_once __DIR__ . '/error_handler.php';
	echo "We're about to call <em>handle_error()</em>...<br />\n";
	echo 'ErrorClass is ', class_exists ('ErrorClass') ? 'undefined' : 'defined', "<br />\n";
	handle_error();
}

register_shutdown_function ('shutdownFunc');

// Make sure errors are printed.
ini_set ('display_errors', 'On');
// Include the file that provokes the error.
require 'throw_fatal_error.php';


<?php
/**
 * error_handler.php
 * -----------------
 * Defines a function that simply prints a message.
 */
function handle_error () {
	echo "handle_error() is here<br />\n";
}


class ErrorClass extends \stdclass {}


<?php
/**
 * throw_fatal_error.php
 * ---------------------
 * Declares two classes with the same name, which throws a fatal error.
 */
namespace test;

class aclass {}

class aclass extends \stdclass {}


Expected result:
----------------
A «Fatal error: Cannot redeclare class aclass» should be thrown» but the following message should also be printed:
  «handle_error() is here»

Actual result:
--------------
No «handle_error() is here» message is printed the following is printed instead:
  «Fatal error: Call to undefined function handle_error()»

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-03-11 18:09 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-03-11 18:09 UTC] nikic@php.net
This has been fixed in PHP 7: https://3v4l.org/EsDVZ

Presumably the problem was some namespace state leaking between nested compiles.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 11:01:30 2024 UTC