per http://drupal.org/node/895386 and other issues - update functions should basically not do anything except DB queries and the like.
They should not invoke hooks.
chx, ksenzee, and I (plus sun for part) debated how core can make sure contrib updates are written correctly, while also supporting use of update functions for "staging" updates (in-code changes like programmatic content creation, etc) in a site-specific module.
Conclusion:
use hook_update_dependencies() => http://api.drupal.org/api/function/hook_update_dependencies/7
unless you specify something like:
$dependencies['mymodule'][7000] = array('bootstrap_full' => TRUE);
You will not get a full bootstrap and cannot call any API functions or hooks.
Any module that asks for a full bootstrap and is actually disabled will result in an Exception, so it will not be permitted to run.
Comment | File | Size | Author |
---|---|---|---|
#13 | drupal8.update-upgrade.13.patch | 9.71 KB | sun |
#8 | no_modules_update.patch | 25.57 KB | chx |
#6 | drupal.update-bootstrap.6.patch | 1.38 KB | sun |
Comments
Comment #1
Damien Tournoud CreditAttribution: Damien Tournoud commentedThis sounds like a pretty good idea.
Thanks to the dependency system, we can just not run this update (and any update that depend on it). There is no need to prevent updates from other modules from running.
Comment #2
chx CreditAttribution: chx commentedThe reason we are throwing exceptions is to prevent misuse. Site specific modules wont be disabled and contrib should not use this.
Comment #3
sunSo what happens if my module's data depends on my module's own info hook being implemented by other modules, and I've to call that hook to remotely be able to update stored data? (since without gathering info from the modules, there is insufficient information about the already stored data, so updates can't be performed)
Comment #4
pwolanin CreditAttribution: pwolanin commented@sun - I think in this case you would have to ask for a full bootstrap, but also put a check into your update function to abort if the module is disabled.
Comment #5
chx CreditAttribution: chx commentedsun's issue is a whole another bag of hurt, I opened #923432: Disabled modules break update
Comment #6
sunSo something like this.
Comment #7
chx CreditAttribution: chx commentedQuite probably the solution for both problems (which might actually be re-merged into this one now) is to change what list of modules an update can require. The bootstrap will be full anyways (so please disregard sun's patch), but the module_list will be different: none (default), enabled, installed. Also we probably want to provide update helpers that manipulate module_list in these ways.
Hopefully, modules asking for enabled or installed modules to be module_listed will not do major upgrades and the hooks they fire won't hit functions that tank because their tables are not yet updated. We can't do much more than hope. Of course we will first run those updates that need no modules so this hope is well founded.
After applying the outstanding cleanup criticals, I was able to get the BasicUpgradePathTest pass with no modules in module_list (and only field and field_sql_storage needs to be drupal_loaded even).
Comment #8
chx CreditAttribution: chx commentedThis is the code that passes the Basic update but does not yet implement the per update module_list functionality. That wont' be hard. This is a lot of change but it's mostly from existing issues so as those get in, this will shrink.
Comment #9
sunYeah, something like that. For the other issue, just provide a update_load_installed_modules(), which can be invoked by individual updates (but should be avoided).
Comment #10
sunComment #12
sunOne more quick note: The preliminary update.php info/selection forms still have to do a full, regular bootstrap. I (1) have a contrib module that exposes functionality on those forms (do an automated database backup before updating) and (2) once had the need to output a special upgrade warning for a contributed module. Thus, limiting module_list() during actual execution of updates is fine, but please not before or after.
Comment #13
sunI wish it wouldn't be the case, but I unintentionally and unexpectedly ran into this problem with:
#1215104: Use the non-interactive installer in WebTestBase::setUp()
This time though, it's not a contrib module or similar doing it wrong, it's the very Drupal core update.php script that runs into core module incompatibility and DI service container issues when performing an upgrade from D7.
The one-line summary is: The upgrade path with an enabled Locale module from D7 is broken.
The amount of symptoms I had to go through in debugging the actual upgrade path test failures (after changing the upgrade path tests to produce proper exceptions) were insanely excessive. The bottom line, however, is:
So:
Attached patch fixes the update.php environment to limit the module list to System module only.
However, it specifically takes #12 into account, which means that the module list has to be "locked down" and "unlocked" more than once within the update process. Turns out that Drupal core requires this itself - specifically, but not limited to the
hook_requirements()
check that happens within update.php.Comment #14
catchWhat's calling t()?
Comment #15
sunThe call chain was:
At first, I tried to adjust the code to not trigger this call chain. But then I realized that this certainly isn't the only possible error that can occur, since we're changing so many early bootstrap things for D8.
So I recalled that we had that discussion in this issue, and that we actually wanted to lock down the module list for D7 already.
Doing so properly resolved the cause for the early update.php bootstrap error. And at the same time, it revealed a couple of module updates that are calling into module API functions during the upgrade path.
I still think it's the right thing to do. It will prevent anyone from writing a bogus update in the future (although, sure, you can hack around it and manually unlock the module list, but then you're doing it really wrong).
Comment #16
catchThis just looks like another case of #1134088: Properly document update-api functions to me. We can't rely on locking down the module list to avoid that issue, since for example a call to url() could trigger a path alias lookup and the db might not be ready for that either.
Comment #17
sunI don't really understand the relation to #1134088: Properly document update-api functions — that one is about using the right/schema-compatible helper functions to retrieve things in module updates. This change here is about preventing module hooks from being invoked.
You're right in that even with this patch, there are still functions unrelated to module hooks that might trigger DB lookups on a wrong schema. However, for such functions, we either need to provide update helpers, or they might as well be replaced with update process compatible services (e.g., #1269742: Make path lookup code into a pluggable class for the concrete url() example).
The essence of this patch is:
1) No more module hook invocations during the update process.
2) No more access to API functions defined in .module files during the update process.
3) However, retain hook_requirements() checks during update.php.
Comment #18
catchNo that one's also about preventing module hooks from being invoked, since we don't know if the hooks might rely on a schema definition somewhere that hasn't been upgraded yet, which is why we need to document it properly. I'd prefer it if we threw an exception when module_implements() is called in update.php so there's strict errors thrown whenever this happens, rather than have a situation where it's OK to call some non-database/schema API functions but not others since that'll be even more confusing than the blanket rule we have now.
Comment #19
sunWell, while a conditional exception to module_implements() & co could be easily added to this patch, I don't think it's possible, since the update.php script itself needs at least access to a few System module hook implementations; e.g., to construct a form with form elements, and to theme/render various pieces on the update.php pages.
Specifically regarding schema access, please note that I also filed #1774104: Replace all trivial drupal_write_record() calls with db_merge()
Comment #20
sunGiven the pushback here, I'll try to remove the changes from #1215104: Use the non-interactive installer in WebTestBase::setUp() and work around the LanguageUpgradePathTest failures in some other (yet unknown) way; i.e., effectively retaining the upgrade path error that is currently in HEAD.
Comment #21
webchickI really hate to do this, since it pushes us back up over thresholds, but this is a critical bug as far as I can tell, since it breaks the upgrade path.
Comment #22
sunThe existing patch implements exactly what this issue proposed and discussed since its beginning:
Locking down the module list for the entirety of update.php. Which means that .module files are not loaded in the first place, which in turn means that no API functions can be called, and obviously also that no hooks are invoked.
It sounds like @catch doesn't want to do this anymore. If that's the case, then the proper action to do for this issue is "won't fix." If so, some reasoning would be good to have.
In any case, there's a patch for the proposal, and other issues were able to work around the update.php situation in different ways.
Comment #23
David_Rothstein CreditAttribution: David_Rothstein commentedRelated: #2001310: Disallow firing hooks during update
Comment #31
pameeela CreditAttribution: pameeela commentedAs part of the Bug smash initiative, we are triaging issues that are marked 'Postponed (maintainer needs more info)'. Based on the lack of follow up, we believe this issue is no longer relevant so I am marking it 'Closed (outdated)'.
Comment #32
xjmDiscussed with @catch and this issue was actually a duplicate of #2001310: Disallow firing hooks during update. The change was later reversed in #2233403: Let update.php invoke hooks again, and we eventually added a workaround for these sorts of problems with the addition of post-update hooks.
So, adding those to the related issues and closing as a duplicate. Thanks!