Enabling some modules that have dependencies on other modules can lead to a completely broken site. Something goes wrong while resolving and enabling the dependencies.
Steps to reproduce:
* Download Rules 2 for Drupal 7 http://drupal.org/project/rules
* Download Entity API http://drupal.org/project/entity
* Enable Rules2 and confirm enabling the dependencies Entity Metadata and Entity CRUD API
* This produces a fatal error all over your site.
Workaround:
* Enable Entity Metadata and Entity CRUD API separately _before_ you enable Rules2 and everything works as expected.
Rules implements hook_init(), so maybe that hook is called before the dependencies are resolved - just a guess.
Comment | File | Size | Author |
---|---|---|---|
#29 | 742972-entity-cache-test.patch | 2.25 KB | klausi |
#27 | 742972-entity-cache-test.patch | 2.1 KB | klausi |
#25 | 742972-module-enable.patch | 1.63 KB | klausi |
#17 | 742972-entity-cache-test.patch | 3.58 KB | klausi |
#15 | 742972-entity-cache-test.patch | 3.64 KB | klausi |
Comments
Comment #1
BerdirOk, I found the issue. It's the entity cache.
rules2 implements hook_watchdog() and then tries to get entity information.
It is a bit tricky to reproduce manually because it does work once the modules have been installed correctly once, because the entity cache actually contains the information about those entities at that point.
Therefore, I'm attaching a hacked version of the Module dependency test which uses rules and the entity modules. That one fails without the changes in module.inc but obviously needs those modules to be present so it can only be manually tested.
We probably need a proper test case for this.
Comment #3
klausiThe first patch works fine for me and fixes the bug. There is already a system_dependency_test.module, should we implement hook_watchdog() there and try to access entity information?
Comment #4
fagoHm, shouldn't it suffice to implement a module providing a new entity and checking for the existence of the new entity_info directly after enabling the module?
Comment #5
klausi@fago: I played around a little bit and wrote a test case to check the entity information right after enabling the module. This works without the patch from Berdir, so no, this is not sufficient. Maybe I haven't tested it the way you meant to.
Comment #6
fagoHm, strange. Probably you should invoke entity_get_info() before calling module_invoke too, so you make sure the cache is actually filled.
Comment #7
fagoStrange, I just installed a new site and I didn't experience any problems!?
Comment #8
klausiIs still broken for me on a clean Drupal install.
Comment #9
klausiSome further tests. The first one passes and does not trigger the error, the second one uses the module page for module enabling and fails. I'm curios what test-bot thinks about it.
Problem: in order to use the test modules on the modules page they need to be visible, which is ugly.
I'm not sure about where to put these tests, so filenames are not final.
Comment #11
BerdirTry it without that part. This already enables the test module, and the module_enable() call in your code doesn't doanything then...
Powered by Dreditor.
Comment #12
klausi*facepalm*
You are absolutely right, I just overlooked that.
This patch now finally works for me and catches the bug with a proper test.
Comment #13
klausiComment #14
fagooh, of course.. Great that we have a working test case now. The fix is simple and looks fine, but the test case needs some work:
* The test case does not really test the entity cache, it tests module enabling and makes sure the entity cache is fine. Thus I think the test case should put to the other module enable tests.
* @entity_cache_test_watchdog() - we need to document why this is there and what it does. Else that's just confusing for anyone reading the code.
Comment #15
klausiaddressed points from #14.
Comment #16
catchPlease use entity_info_cache_clear() which encapsulates the drupal_static_reset() and the cache_clear_all().
Also I feel like module.inc shouldn't know anything about entities - i.e. this should be a hook implementation (system_modules_enabled()?), but I have doubts that actually fix the bug given the general mess in module enabling.
Comment #17
klausinow using entity_info_cache_clear().
As far as I can see implementing hook_modules_enabled() will be too late, as watchdog() is called before in module_enable().
Comment #18
catchYeah let's deal with interdependencies between includes in another issue, probably D8. It would also be nice to only clear this cache if the module being enabled implements hook_entity_info() or hook_entity_info_alter(), but that's not worth special casing here given all the other stuff that gets cleared regardless.
Comment #19
catchLooks like the patch was committed here along with another commit, without adding the new test module. So we either need to roll back the patch or commit the test module.
Comment #20
webchickCommitted to HEAD!
Comment #22
sun#910190: Entire schema cache needlessly loaded on all pages reveals that blatantly assuming a completed installation in hook_watchdog() is a weird assumption. This patch does not even check the actual watchdog message, so it expects that any watchdog message is the watchdog message this test is targeting. I'm not sure what exactly has been tried to asserted here.
Comment #23
sun1) So this should have been hook_modules_installed().
2) It's invalid do define a base table that does not exist.
My patch over in #910190: Entire schema cache needlessly loaded on all pages corrects this.
assertNotNull()? That does not assert any expectation.
Powered by Dreditor.
Comment #24
klausiWhy? If a hook in a module is called a developer should be able to assume that the own module has been installed completely with dependencies. Otherwise we should document extensively that hook_watchdog() is an exception and gets called randomly. Now that would be weird to me.
Comment #25
klausiThe test case was designed to trigger just a single watchdog message (during module_enable()). As far as I can see there are 2 watchdog() calls now, so we want to make sure that we call watchdog() only after the module was installed and enabled completely. In my opinion hook_watchdog() should be safe with the downside of delaying the watchdog() calls to the end of module_enable().
Patch attached.
Comment #26
sunThanks!
For that, we don't have to change the watchdog invocations, but have to fix the entity_cache_test_watchdog() implementation instead. Additionally,
- change the assertNotNull() to something that actually asserts an expectation (I think you are expecting a fully loaded and fully usable entity info array - that is what needs to be asserted accordingly, if so).
- remove the 'base table' from hook_entity_info().
- Heavily improve the comments on entity_cache_test_watchdog() to let readers understand why this test looks a bit weird.
Comment #27
klausiNot critical anymore, as we just want to improve the test here.
I'm not sure how to improve the comments .. what would you like to see?
Comment #28
sunCan we clarify this a bit more? Instead of telling what it does (already visible in the code), we need to explain the "why" + expectations. Something along the lines of:
This hook is called during module_enable() and since this hook implementation is invoked, we have to expect that this module and dependent modules have been properly installed already, so we expect to be able to retrieve the entity information that has been registered by the required dependency module.
Much better, thank you!
Powered by Dreditor.
Comment #29
klausiAlright, how about this?
Comment #30
sunMuch better, thank you!
Comment #31
sun#29: 742972-entity-cache-test.patch queued for re-testing.
Comment #32
webchickCommitted to HEAD. Thanks!