There seem to be a number of problems with modules or nodes with PHP code doing funny things when their code is invoked during hook_cron(). Many of these problems could be avoided by making code conditional on not being called by cron. But there is the problem of detecting whether or not this code is being invoked by cron.

Hacks:

I suggest that there should be a new drupal API function defined to detect whether or not a cronjob is running.
Return value: TRUE if hook_cron() is being run, FALSE otherwise. This function should not return TRUE just because the cron_semaphore is grabbed or just because hook_cron() _was_ called -- I think this latter note is important because otherwise poormanscron might be broken(?)
Name: Please come up with a better name, my best idea is cron_running_hooks(). This name hopefully makes it obvious that the function will not return TRUE just because cron_semaphore is locked.

My concerns: I do not know how the ``queues'' stuff works. It would seem that cron_running_hooks() should return TRUE when queues are being run. Thoughts?

Sorry for the patch against DRUPAL-6, have made modifications to HEAD but couldn't test them yet because I don't have PDO installed yet.

Comments

franz’s picture

franz’s picture

Could be only cron_running, to avoid being confused with another hook...

franz’s picture

Status: Active » Needs review

Triggering test to make issue alive

Status: Needs review » Needs work

The last submitted patch, drupal-DRUPAL-6-cron_running_hooks.patch, failed testing.

franz’s picture

Title: Add cron_running_hooks() » Add drupal_cron_is_running()
Status: Needs work » Needs review
StatusFileSize
new1.31 KB

I renamed the function to fit the pattern and re-rolled the patch

franz’s picture

Issue tags: +Needs tests

Would be nice to have some tests here to ensure cron runs code that has drupal_goto().

franz’s picture

Issue tags: -Needs tests

#5: 888998-drupal-cron-is-running.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Needs tests

The last submitted patch, 888998-drupal-cron-is-running.patch, failed testing.

franz’s picture

Status: Needs work » Needs review
StatusFileSize
new1.47 KB

Re-rolling

xjm’s picture

Some mechanism like this seems like a really good idea. I'm hesitant about adding it to the globals, though. Maybe someone smarter than me can weigh in on that.

Here's a couple of minor cleanups.

+++ b/includes/common.incundefined
@@ -5083,6 +5089,23 @@ function drupal_cron_run() {
+ * Check if cron hooks are being called and queues are being run.

Minor thing, but I'd change this to "Checks whether cron hooks are being called and queues are being run."

+++ b/includes/common.incundefined
@@ -5083,6 +5089,23 @@ function drupal_cron_run() {
+ *     - queues are being processed right now.

And let's capitalized "Queues" here, I think.

Also, note that the Drupal 8.x patch will need to be rerolled, because the core directory structure for Drupal 8 has now changed. (For more information, see #22336: Move all core Drupal files under a /core folder to improve usability and upgrades). When the patch has been rerolled, please set the issue back to "Needs Review."

Tagging as novice for the task of rerolling the Drupal 8.x patch, including fixing the two points I describe above.

If you need help rerolling this patch, you can come to core office hours or ask in #drupal-gitsupport on IRC.

xjm’s picture

Status: Needs review » Needs work
Issue tags: +Novice

Except there was a validation error and I failed to set the status or the tag. Oops.

kathyh’s picture

Status: Needs work » Needs review
StatusFileSize
new1.46 KB

Patch for #10 (sans any mod to the concept of adding it to the globals).

kathyh’s picture

StatusFileSize
new1.46 KB

fixed spaces introduced in #12

franz’s picture

Issue tags: -Novice
StatusFileSize
new1.63 KB

Yes, I was thinking, and leaving the global also did not make sense if using a function, so I made it a static variable, not sure if that was the best way of implementing it.

tstoeckler’s picture

Status: Needs review » Needs work

Why not kill the function entirely and do:

variable_set('cron_running', TRUE);
// Run cron.
...
variable_det('cron_running');

Then instead of

if (drupal_cron_is_running()) {
 ...
}

people can do

if (variable_get('cron_running', FALSE)) {
  ...
}

??
I think that would be a little less overhead code-wise.

xjm’s picture

Assigned: Unassigned » xjm

#15 seems like a better solution to me as well, especially since memory overhead is a concern on cron. I'll roll a patch and test with that method.

franz’s picture

Mmm, I don't like the idea. This value is supposed to be used to determine if the CURRENT request is a cron run.

variable_set() will cause all parallel requests to believe they're being run on a cron.

franz’s picture

Also, memory overhead is minimal (couple of lines of code and a static variable?) and O(1), so it's not that much of a concern.

xjm’s picture

#17: Oh, that is an excellent point. Doh. So #14 is the correct solution, then.

I'll rewrite my test for #14 instead.

xjm’s picture

Status: Needs work » Needs review
StatusFileSize
new3.73 KB

Attached test-only patch tests whether drupal_cron_is_running() returns the expected value at various points. (Note: The patch includes drupal_cron_is_running() to avoid undefined function fatals, but does not use it during cron.) Should fail.

xjm’s picture

+++ b/core/modules/simpletest/tests/common_test.moduleundefined
@@ -251,12 +251,32 @@ function common_test_js_and_css_querystring() {
\ No newline at end of file

Whoops. I'll fix this in the combined patch. This won't affect the demonstration that the test fails, though. :P

franz’s picture

Status: Needs review » Needs work
+++ b/core/includes/common.inc
@@ -5207,6 +5213,30 @@ function drupal_cron_run() {
+ * @param $value - If not null, set the boolean value of the variable

Just noticed this is not conforming to doc standards... Should be a newline sentence with a period.

23 days to next Drupal core point release.

xjm’s picture

Status: Needs work » Needs review

#22 Did you look at the most recent patch? I already changed that.

Still waiting on testbot here before I upload the combined.

Status: Needs review » Needs work

The last submitted patch, cron-running-tests-888998-20.patch, failed testing.

xjm’s picture

Status: Needs work » Needs review
StatusFileSize
new4.44 KB

'Bout time. Fails on the correct assertion. Now, the combined patch. This is the one to review.

franz’s picture

Status: Needs review » Needs work

No, sorry. Test failed fine, we're almost done here. =)

franz’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

Ops, cross-post...

xjm’s picture

+++ b/core/includes/common.incundefined
@@ -5207,6 +5213,32 @@ function drupal_cron_run() {
+ *   - Queues are being processed right now.

Oh, I just realized that I didn't add test coverage for this case.

Oh, wait. Actually, I think that this functionality hasn't been added yet. I think we'd need to add setting and unsetting the flag around the bit below? Can anyone weigh in on whether this is correct (and something we want to do) before I reroll anything again?

  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
franz’s picture

Do you mean setting the same flag when processing any queue?

xjm’s picture

#29: Hmm sorry, I don't understand the question. Maybe too early in the morning. :)

This is what I mean. Change the snippet in #28 to:

  // Flag that queued cron items are currently being run.
  drupal_cron_is_running(TRUE);
  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
  // Flag that queued cron items are no longer being run.
  drupal_cron_is_running(FALSE);

The comments for drupal_cron_is_running() appear to claim that we're doing this, but we're not yet.

franz’s picture

Yes, that's it, I guess this makes it complete.

xjm’s picture

Status: Needs review » Needs work

Alright, will try to add that and come up with some test coverage for it.

xjm’s picture

Assigned: xjm » Unassigned
Issue tags: +Needs tests, +Novice, +Needs reroll

So, three tasks:

  1. Reroll the patch to apply against current 8.x. Note that files have moved around; common_test.module is now inside core/modules/system/tests and CronRunTestCase will have been renamed and moved for PSR-0; look in core/modules/system/lib/Drupal/system/tests//
  2. Update the patch with the snippet in #30.
  3. Add additional test coverage for when the flag should be TRUE.
hawkeye.twolf’s picture

Status: Needs work » Needs review
StatusFileSize
new5.12 KB

I've re-rolled the patch and added drupal_cron_is_running() around the queue code (tasks 1 and 2 from #33).

Task "3. Add additional test coverage for when the flag should be TRUE." from #33 still needs to be addressed.

Status: Needs review » Needs work

The last submitted patch, cron-running-combined-888998-34.patch, failed testing.

hawkeye.twolf’s picture

Status: Needs work » Needs review
StatusFileSize
new737 bytes
new5.15 KB

Whoops - patch fixed now, plus an interdiff.

hawkeye.twolf’s picture

Here's a few more details about my patch. It patch contains two things: (1) the reroll to reflect the changed file structure and line numbers of the PSR-0 testing scheme, and (2) the added code to use the new drupal_cron_is_running() function around the processing of queued cron tasks.

The interdiff shows the changes between the reroll and the added code (no interdiff for the reroll).

disasm’s picture

Issue tags: -Needs reroll
StatusFileSize
new5.1 KB

reroll!

Status: Needs review » Needs work
Issue tags: -Needs tests, -Novice

The last submitted patch, drupal-cron_is_running-888998-38.patch, failed testing.

disasm’s picture

Status: Needs work » Needs review
Issue tags: +Needs tests, +Novice
disasm’s picture

received these same exact failures in 1209674. Appears to be a testbot fluke. Resending.

tstoeckler’s picture

Status: Needs review » Needs work

Some minor improvement suggestions, but all in all I think this warrants a "needs work".

+++ b/core/includes/common.inc
@@ -5068,6 +5081,32 @@ function drupal_cron_run() {
+ * @param $value

I couldn't really come up with a better suggestion, but $value seems random.

+++ b/core/includes/common.inc
@@ -5068,6 +5081,32 @@ function drupal_cron_run() {
+ *   (optional) A boolean flag to indicate whether cron is running, or NULL to
+ *   return the saved value.  Defaults to NULL.

This makes it sound like you should explicitly pass NULL instead of just omitting the variable alltogether. I think we could just omit the second clause in the first sentence.

+++ b/core/includes/common.inc
@@ -5068,6 +5081,32 @@ function drupal_cron_run() {
+ *   - Queues are being processed right now.

I think this should mention that this only applies to cron queues, i.e. queues that have set the cron key.

+++ b/core/includes/common.inc
@@ -5068,6 +5081,32 @@ function drupal_cron_run() {
+  static $drupal_cron_is_running;
+
+  if (!isset($drupal_cron_is_running)) {
+    $drupal_cron_is_running = FALSE;
+  }

This should be simply $drupal_cron_is_running = FALSE;

That said, the variable is too verbose. The drupal part is superfluous at the very least.

franz’s picture

Status: Needs work » Needs review
StatusFileSize
new4.99 KB

Addressed #42

Status: Needs review » Needs work

The last submitted patch, drupal-cron_is_running-888998.patch, failed testing.

tstoeckler’s picture

+++ b/core/includes/common.inc
@@ -5068,6 +5081,28 @@ function drupal_cron_run() {
+    $cron_is_running = $value;

I was gonna mark this RTBC, but the bot is smarter than me...
This should be $running as well.

franz’s picture

Status: Needs work » Needs review
StatusFileSize
new5 KB
franz’s picture

Issue tags: -Needs tests, -Novice

Same here. I think we already have tests.

ParisLiakos’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/tests/modules/common_test/common_test.moduleundefined
@@ -340,3 +350,14 @@ function common_test_l_active_class() {
+  variable_set($var, drupal_cron_is_running());

Any reason why we introduce a variable here? it should be config

franz’s picture

The reason is that the patch is older than those changes.

franz’s picture

I'm still confused by the new API. Should this be converted to a state or a config?

ParisLiakos’s picture

ah..yes you are right, it should be state

franz’s picture

Status: Needs work » Needs review
StatusFileSize
new5 KB

Let's see now.

Status: Needs review » Needs work

The last submitted patch, drupal-cron_is_running-888998_0.patch, failed testing.

franz’s picture

Status: Needs work » Needs review
StatusFileSize
new4.99 KB

Forgot the variable_get(). Done right this time, hopefully.

tstoeckler’s picture

Status: Needs review » Reviewed & tested by the community

Looks great!

catch’s picture

Status: Reviewed & tested by the community » Needs review

I'm not sure about this. Most of the examples involve doing things like drupal_goto(), which is almost always a bad idea (since it completely halts script execution). This could go wrong for anything invoked by drush, not necessarily just cron.

catch’s picture

Also I'd expect this to tell me whether cron is running on the site at all with the current name - drush ev "print drupal_cron_is_running()" for example.

franz’s picture

re #57... it is meant exactly for that, if it doesn't work, needs to be fixed.

franz’s picture

Status: Needs review » Needs work

I see what you mean, I forgot the original idea about it. We need to set a state there.

franz’s picture

Status: Needs work » Needs review

After reviewing the discussion, I read myself saying that no, the purpose is exactly to tell whether cron is running on current call, so that stuff running inside cron jobs will know it and do things differently.

socketwench’s picture

Issue tags: -Novice

Novice issue cleanup.

gung wang’s picture

Status: Needs review » Needs work

The last submitted patch, 54: drupal-cron_is_running-888998_0.patch, failed testing.

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.

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

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +stale-issue-cleanup

Thank you for sharing your idea for improving Drupal.

We are working to decide if this proposal meets the Criteria for evaluating proposed changes. There hasn't been any discussion here for over 8 years which suggests that this has either been implemented or there is no community support. Your thoughts on this will allow a decision to be made.

Since we need more information to move forward with this issue, the status is now Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.

Thanks!

smustgrave’s picture

Will give this one more bump, if no interest will close in 3 months, thanks all!

smustgrave’s picture

This had a lot of comments so giving 1 final bump.

With

    if (!$this->lock->acquire('cron', 900.0)) {
      // Cron is still running normally.
      $this->logger->warning('Attempting to re-run cron while it is already running.');
    }

Is this still needed?

mjpa’s picture

I'm not sure it's needed as mentioned in previous comments some of the scenarios aren't advised anyway.

If its something seen as a good thing to have, I'd favour adding a method to the cron service rather than checking the lock. Another module could change the cron service and use a different way of setting that cron is running.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.