Problem/Motivation

Early error handling (attempts to display PHP warnings, notices, etc), results in a fatal error since the \Drupal::$container is not yet instantiated.

How to reproduce

Add this line to settings.php:

$config['my.override'] = $undefined_variable_typo;

Load a page, see a WSOD or a fatal error depending on error display settings.

Proposed resolution

Don't rely on the \Drupal::$container for displaying errors early on.

Remaining tasks

Fix it.

User interface changes

Will display errors outside of drupal_set_message() if they are thrown early enough.

API changes

No public API changes.

Original report by eule

Hi, i just try out the new d8 dev14+13 on a new environment. running

  • ubuntu 14.04 trusty
  • hhvm
  • nginx1.6.0
  • mariadb10.0

after i upload all and visit the root i become this error msg.

If you have just changed code (for example deployed a new module or moved an existing one) read http://drupal.org/documentation/rebuild
Additional uncaught exception thrown while handling exception.
Original

BadMethodCallException: Call to a member function get() on a non-object (NULL) in Drupal::logger() (line 647 of /var/www/xxx/core/lib/Drupal.php).
Drupal::logger('php')
_drupal_log_error(Array, )
_drupal_error_handler_real(2048, 'It is not safe to rely on the system's timezone settings. Please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin' for 'CEST/2.0/DST' instead', '/var/www/xxx/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php', 206, Array)
_drupal_error_handler(2048, 'It is not safe to rely on the system's timezone settings. Please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin' for 'CEST/2.0/DST' instead', '/var/www/xxx/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php', 206, Array)
DateTime->__construct('', Object)
Symfony\Component\HttpFoundation\Response->__construct('', 302, Array)
Symfony\Component\HttpFoundation\RedirectResponse->__construct('/core/install.php')
Drupal\Core\DrupalKernel::createFromRequest(Object, Object, 'prod')

Additional

BadMethodCallException: Call to a member function get() on a non-object (NULL) in Drupal::moduleHandler() (line 414 of /var/www/xxx/core/lib/Drupal.php).

Drupal::moduleHandler()
_drupal_maintenance_theme()
drupal_maintenance_theme()
_drupal_log_error(Array, 1)
_drupal_exception_handler(Object)

after this i go to ./core/install.php here works all fine to the point of the install. white site http://www.example.com/core/install.php?langcode=de&profile=standard tables are in db created but just 15

if i visit my root again i become now this error msg

Warning: array_keys() expects parameter 1 to be an array or collection in Drupal\Core\Authentication\AuthenticationManager->handleException() (line 185 of core/lib/Drupal/Core/Authentication/AuthenticationManager.php).
    Warning: array_intersect() expects parameter 2 to be an array or collection in Drupal\Core\Authentication\AuthenticationManager->handleException() (line 185 of core/lib/Drupal/Core/Authentication/AuthenticationManager.php).
    Warning: Invalid argument supplied for foreach() in Drupal\Core\Authentication\AuthenticationManager->handleException() (line 191 of core/lib/Drupal/Core/Authentication/AuthenticationManager.php).

Page not found
The requested page "/" could not be found.

hope it helps

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eule’s picture

Issue tags: +hhvm
eule’s picture

Priority: Normal » Critical

hi,
i put the Priority higher because i test in my environment Drupal7 & Wordpress. Both CMS and Bloggin Systems working in my environment. So this seems to me a Problem with the HHVM compatibility.

If you know more about it change the Priority back. Thanks

eule’s picture

HHVM error LOG

\nFatal error: Cannot override final method ReflectionClass::getNamespaceName() in /var/www/xxx/core/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionClass.php on line 25
\nNotice: Undefined index: 16777217 in /var/www/xxx/core/includes/errors.inc on line 62
\nNotice: Undefined index: 0 in /var/www/xxx/core/lib/Drupal/Core/Utility/Error.php on line 127
\nNotice: Undefined index: file in /var/www/xxx/core/includes/errors.inc on line 73
\nNotice: Undefined index: line in /var/www/xxx/core/includes/errors.inc on line 74
eule’s picture

Priority: Critical » Major
eule’s picture

Project: » Drupal core
Version: » 8.0.x-dev
Component: Code » ajax system
Priority: Major » Critical
eule’s picture

Component: ajax system » other
eule’s picture

Issue summary: View changes
eule’s picture

Issue summary: View changes
swentel’s picture

Priority: Critical » Normal

HHVM compatibility is tracked in #2165377: [meta] HHVM compatibility - we should add this as a sub issue of it, but this is not critical atm.

eule’s picture

dawehner’s picture

Is this still active?

eule’s picture

not sure yet. but i think so.

eule’s picture

Nope this seems not to be fixed!
i setup a new site with latest D8 dev and updated the system to hhvm 3.3.0

drupal is not installed and i visit my page. this redirects me not to ./core/install but gives me a huge error message like i here postet - i go to ./core/install and install drupal ...this works! and drupal runs!

this i got in my hhvm log
\nFatal error: Uncaught exception 'BadMethodCallException' with message 'Call to a member function get() on a non-object (NULL)' in /var/www/example/core/lib/Drupal.php:138\nStack trace:\n#0 /var/www/example/core/includes/bootstrap.inc(910): Drupal::service()\n#1 /var/www/example/core/includes/errors.inc(221): drupal_set_message()\n#2 /var/www/example/core/includes/errors.inc(77): _drupal_log_error()\n#3 /var/www/example/core/includes/bootstrap.inc(1062): _drupal_error_handler_real()\n#4 (): _drupal_error_handler()\n#5 /var/www/example/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php(206): DateTime->__construct()\n#6 /var/www/example/core/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RedirectResponse.php(44): Symfony\\Component\\HttpFoundation\\Response->__construct()\n#7 /var/www/example/core/lib/Drupal/Core/DrupalKernel.php(215): Symfony\\Component\\HttpFoundation\\RedirectResponse->__construct()\n#8 /var/www/example/index.php(20): Drupal\\Core\\DrupalKernel::createFromRequest()\n#9 {main}

maybe again a hhvm issue?

jhedstrom’s picture

Title: BadMethodCallException: Call to a member function get() » Early error handling can result in fatal error (Call to a member function get() on a non-object)
Priority: Normal » Major

I don't think this is specific to hhvm, I think the error thrown is simply an uncaught exception instead of a fatal error.

This error can be reproduced by simply adding $foo = $bar in settings.php. This tries to display a PHP notice, but results in a far worse fatal error since the container is not yet instantiated in \Drupal:

( ! ) Fatal error: Call to a member function get() on a non-object in /Users/jhedstrom/work/contributions/cores/drupal-8/core/lib/Drupal.php on line 161
Call Stack
#	Time	Memory	Function	Location
1	0.0044	245376	{main}( )	../index.php:0
2	0.0274	1356352	Drupal\Core\DrupalKernel::createFromRequest( )	../index.php:22
3	0.0332	1630520	Drupal\Core\Site\Settings::initialize( )	../DrupalKernel.php:220
4	0.0335	1644440	require( '/Users/jhedstrom/work/contributions/cores/drupal-8/sites/default/settings.php' )	../Settings.php:108
5	0.0336	1649688	_drupal_error_handler( )	../Settings.php:683
6	0.0342	1694528	_drupal_error_handler_real( )	../bootstrap.inc:867
7	0.0360	1849352	_drupal_log_error( )	../errors.inc:77
8	0.0360	1850584	Drupal::root( )	../errors.inc:202

This surfaced in the Drush issue queue as well when we were missing an argument to a method. What should have been a PHP warning resulted in this same fatal error.

jhedstrom’s picture

Issue summary: View changes
jhedstrom’s picture

Priority: Major » Critical
Status: Active » Needs review
Issue tags: +DX
FileSize
1.72 KB

This resolves the issue, not in the most elegant way though. It also results in unthemed notices/warnings at the top of the page if the error is thrown too early.

I'm bumping to critical since this seems like a crucial DX issue.

jhedstrom’s picture

Issue summary: View changes
znerol’s picture

This is the same issue as #2223575: PHP Fatal error: Call to a member function get() on a non-object which has other issues linked as well.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/includes/errors.inc
    @@ -198,10 +198,13 @@ function _drupal_log_error($error, $fatal = FALSE) {
    +      if ($container = \Drupal::getContainer()) {
    

    Rather than getting the container here we should use hasService('app.root')

  2. +++ b/core/includes/errors.inc
    @@ -218,7 +221,14 @@ function _drupal_log_error($error, $fatal = FALSE) {
    +      if ($container) {
    

    Let's be honest here are check if we have the page_cache_kill_switch service instead.

znerol’s picture

Let's be honest here are check if we have the page_cache_kill_switch service instead.

Or session_manager, that might be a bit more obvious for people reading the code?

alexpott’s picture

@znerol yep that makes sense +1

catch’s picture

I think this is a duplicate of an old issue, but I can't find that old issue at the moment.

What about calling set_error_handler() and set_exception_handler() at the end of, or just after DrupalKernel::initializeContainer() instead of DrupalKernel::bootEnvironment() - then the container dependency is met.

If there's an exception while building the container you get an unthemed error but that's an extremely unlucky production error to have.

Adding the explicit check for the session service inside the error handler is decent too though.

jhedstrom’s picture

Status: Needs work » Needs review
FileSize
1.38 KB
1.57 KB

I should have read further through errors.inc, \Drupal::hasService() is what I was looking for.

dcrocks’s picture

jhedstrom’s picture

I posted #24 without seeing #23.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

That itself is already an improvement, one less reason to fail during the error handling.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

re #25 not really. We still need to avoid calling the session_manager if it does not exist yet. This patch would be no different if that had landed already.

I think we should explore moving the error handler setting in DrupalKernel::boot() in another patch. As @dawehner says this makes things better already. This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 99d219a and pushed to 8.0.x. Thanks!

  • alexpott committed 99d219a on 8.0.x
    Issue #2317913 by jhedstrom: Early error handling can result in fatal...
znerol’s picture

There might be multiple duplicate issues about this, e.g. #2223575: PHP Fatal error: Call to a member function get() on a non-object. Those should be closed as duplicate.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.