Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem
- drupal_rebuild() can run into error conditions itself, triggering Drupal's error/exception handler, but those handlers require a working system/service container + theme system. → Fatal error caused in error handler, hiding the actual error.
- The error handler itself attempts to iterate over function arguments in a backtrace, without checking whether 'args' is set → PHP notice within error handler, recursively triggering error handler.
- DrupalKernel::discoverServiceProviders() throws a PHP warning in case an installed module (contained in system.module.yml) no longer exists in the filesystem → Combined with aforementioned error handler issue, the container rebuild fails.
Comment | File | Size | Author |
---|---|---|---|
#7 | drupal8.rebuild-errors.7.patch | 1.89 KB | sun |
drupal8.rebuild-errors.0.patch | 2.73 KB | sun | |
Comments
Comment #1
damiankloip CreditAttribution: damiankloip commentedGood work! I thought we would run into issues at some point due to the drupal error handling with no container, in their current form. It's better you've found this sooner. These are pretty trivial changes, that make all the difference.
Looks good, and fixes the issue. Replicated on local.
Comment #2
catchUnless this results in a fatal (once the rest of the patch is applied) please leave it in. Those errors are useful and shouldn't be hidden. If it's fatal, then trigger_error() or something.
Comment #3
sunWithout that condition, the rebuild script shows a PHP notice (native PHP error handler) and depending on display_errors in php.ini, it does not redirect.
I guess that could be considered minor.
However, in case the rebuild happens to fail due to other errors/exceptions later on in dfac(), then I'm back to the same error when going back to the actual site:
Putting back the isset() adjustment in DrupalKernel, Drupal at least boots on regular pages again.
So I think we should leave it in and commit the patch as-is.
The ultimate goal of the rebuild script is to recover to a functional container/DrupalKernel state. Whenever you have to manually rebuild, something went terribly wrong and there's a 99% chance that the system contains stale data either way.
Comment #4
damiankloip CreditAttribution: damiankloip commentedSo based on that, back to RTBC?
Comment #5
sunI think so, yes.
Comment #6
webchickZoooooom!
Comment #7
sunAfter further debugging investigations, I now agree that the change to DrupalKernel should not be contained in here, as the container is continuously rebuilt on every request without any kind of notice or warning that something is wrong.
I'll create a separate issue for that problem.
With that debatable change out of the way, I hope we can move forward here now.
Comment #8
sunCreated #2161995: Faulty module cannot be removed from module list; DrupalKernel rebuilds container on every page request
Comment #9
chx CreditAttribution: chx commentedIf the error handler relies on the container that is a bug.
_drupal_get_error_level
handles one such dependency and if there's more then fix it similarly. I seeif (\Drupal::request()->isXmlHttpRequest())
which looks suspicious. I do not know what else is there. But removing the Drupal error handler instead of fixing it is not the solution.Comment #10
sunI'm not able to see the point of trying to get a custom error handler to work in a scenario in which the entire application is known to not be operable?
The custom error handler tries to (1) log using watchdog(), (2) dsm() an error message, (3) initialize the [maintenance] theme, etc.
We can certainly hack the error handler code with further conditionals, but the end result is going to be the same in the concrete case of
drupal_rebuild()
: The custom error handler is not functional, an error must be displayed and/or logged, so you are able to identify the problem and recover.Perhaps you can explain what kind of benefit the custom error handler would have (because I fail to see one), and why we want to use it in a scenario in which it and all of the services it attempts to use cannot work?
Comment #11
chx CreditAttribution: chx commentedMy problem is -- are there other situations where this dependency becomes problematic? Early install errors for example?
Comment #12
sunAll other situations are setting up a special environment and custom container/DrupalKernel, because they already know that services are not available yet. The way that is done is still a big sad mess and should be improved, but that is OT for this issue.
But drupal_rebuild() operates at the opposite end: The only thing it knows is that the application that previously was operable is no longer operable. To which extent, is unknown. It is not able to predict whether the rebuild will succeed or whether it will throw any notices, warnings, errors, or exceptions and break in the middle.
Lastly, drupal_rebuild() does not render an HTML page, but the custom error handler is designed to collect, aggregate, and render errors in a full page output. In turn, we'd only add more spaghetti to the custom error handler and we'd have to add a fragile way to retrieve and render errors in the output of a script that isn't supposed to render a page-alike thing to begin with.
The scope of this issue is limited to the rebuild script. PHP's native error handling does exactly what it is supposed to do and fully matches developer expectations within this limited scope. It is unnecessary to overload it with a custom and fragile behavior.
Comment #13
Anonymous (not verified) CreditAttribution: Anonymous commentedi think i agree with special-casing drupal_rebuild(), and not relying on a working application in any way to report errors during it's running. i think it makes sense that we don't want to rely on a working drupal at all, and we should just use 'normal' php settings during that time. so, RTBC.
Comment #14
xjm7: drupal8.rebuild-errors.7.patch queued for re-testing.
Comment #15
catchThanks for #7.
Agreed on the error handler, this is one place I don't mind whatever special-casing is necessary.
Committed/pushed to 8.x, thanks!