Specifically, if you call a function within hook_hook_info() that in turn calls a hook, you get an infinite loop as soon as you clear the cache. ka-boom!

This is a problem, because very often we'll have dynamic hooks that are per-something. Eg, a hook per-entity-type. (I'm working on a major reworking of the apachesolr module and just ran into this problem.) The obvious, well really only, way to do that is to iterate over entity_get_info()... which in turn calls module_invoke_all('entity_info'), which with an empty cache causes hook_hook_info() to be called... you get the idea.

I'm not entirely certain how to break this cycle, but I don't think that "well don't do that" is a viable solution as it pretty much kills dynamic hooks. Dynamic hooks are, of course, increasingly popular in Drupal and with good reason.

I'm considering adding a semaphore somewhere, but I'm not sure where that would actually, well, work.

Comments

mattyoung’s picture

~

dave reid’s picture

Yeah I'd probably say at this point "don't do that". I don't know how we can best support dynamic hooks with this. Why not generalize your hook to work for all entities (like core's hook_entity_load(), etc.).

Crell’s picture

The hook in question is more like a form alter.

apachesolr_indexer_document_build
apachesolr_indexer_document_$entity_build
apachesolr_indexer_document_$entity_$bundle_build

(And then 3 layers of alter as well.)

Without dynamic hook support in hook_hook_info(), only the first can be moved out of the .module file yet all are useful only when indexing content, which will be happening only on cron anyway so it's pointless to have them loaded all the time.

dave reid’s picture

So why not make it apachesolr_indexer_document_entity_build($entity) and apachesolr_indexer_document_entity_bundle_build($entity, $bundle)? :)

Crell’s picture

For the exact same reason we have hook_form_$form_id_alter(). To allow targeted operations more efficiently.

dave reid’s picture

I just still get the feeling that hook_hook_info() will not work with dynamic hooks at all in D7. If someone clears all caches, both the module_implements and entity info caches will also be empty. We'd have to somehow make sure the entity cache gets generated before the hook cache, but I don't think that's possible...

dave reid’s picture

I guess we could add some kind of wildcard condition like:

  $info['apachesolr_indexer_document_*_build'] = array(
    'group' => 'apachesolr',
    'wildcard' => TRUE,
  );

but that also seems too late for D7.

sun’s picture

I don't think that something along the lines of #7 is too late for D7.

Last resort is to add a static to module_implements() to not recursively invoke hook_hook_info() + prevent caching of recursive calls - but that would (intentionally) break perfectly valid stuff. So in turn, something along the lines of #7 is required.

dave reid’s picture

Status: Active » Needs review
StatusFileSize
new3.4 KB

This is what I had so far.

carlos8f’s picture

Status: Needs review » Needs work
+++ includes/module.inc	17 Nov 2010 17:54:44 -0000
@@ -708,6 +720,44 @@ function module_hook_info() {
+function module_hook_wildcard_info($hook = NULL) {
...
+      foreach (module_hook_info() as $hook_key => $hook) {

Variable name conflict -- here is an (array) $hook, while there is already a (string) $hook defined. I would prefer $hook to always be a string -- to be consistent with the rest of module.inc.

+++ includes/module.inc	17 Nov 2010 17:54:44 -0000
@@ -708,6 +720,44 @@ function module_hook_info() {
 /**
+ * Retrieve a list of what wildcard hooks are explicitly declared.
+ */

More docs! Should include @see hook_hook_info(). hook_hook_info() needs an api.php hunk for the 'wildcard' key. There should also be a note in the docs to avoid invoking hooks inside of hook_hook_info(), and to use a wildcard instead when dynamic hook names need to be grouped.

module_test.* should test the wildcard key.

Note that this also needs some work after #752226: module_invoke() doesn't work with hooks placed in include files via hook_hook_info() lands -- that patch does group/include resolution in module_hook(), which allows module_invoke() to support hook_hook_info(). So this patch would need to ensure that module_invoke() also supports wildcard hook grouping.

carlos8f’s picture

Also, wouldn't be better DX if we could

+++ includes/module.inc	17 Nov 2010 17:54:44 -0000
@@ -708,6 +720,44 @@ function module_hook_info() {
+        if (!empty($hook['wildcard']) && !empty($hook['group'])) {

not require a 'wildcard' key and just do strpos($hook_key, '*') !== FALSE?

catch’s picture

Version: 7.x-dev » 8.x-dev
Priority: Major » Normal
Issue tags: +Needs backport to D7

If no-one ran into this for 7 months it can't be that major.

joericapens’s picture

I ran into a real problem because of this:

http://drupal.org/node/1415278

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

catch’s picture

Issue summary: View changes
Status: Needs work » Closed (works as designed)

Closing as 'works as designed', this is just unsupported.

We should be instead moving towards getting rid of hook_hook_info() via issues like #2237831: Allow module services to specify hooks.