This looks like a bug although maybe I'm just not understanding something.
If you look at drupal_cron_run() it has lock functionality which prevents more than one cron process from running at once.
However, the code which processes queue items during cron lives outside of that lock, and thus queue items will be processed every single time cron is called.
This could be an issue especially when combined with the "poormanscron" feature in core. For example, when one (unlucky) person triggers the cron process and gets a slow page request, then before it's complete everyone else who happens to visit the site during that time period seems like they will trigger the processing of queue items (even if they don't trigger the full cron processing) and therefore they might all get slow page requests too..
| Comment | File | Size | Author |
|---|---|---|---|
| #22 | interdiff.1875020.5-22.txt | 3.32 KB | longwave |
| #22 | 1875020-22.patch | 3.93 KB | longwave |
| #5 | cron-queue-1875020-5.patch | 620 bytes | slip |
| #2 | cron-queue-1875020-2.patch | 2.14 KB | David_Rothstein |
Issue fork drupal-1875020
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 1875020-cron-queue-gets
changes, plain diff MR !1630
Comments
Comment #1
jhodgdonActually, I don't think this is really a problem. Cron queue jobs have to be written so that they are independent and can be done in a queue -- meaning that they sit there and wait for some process to come along, read them from the queue, and do them. There are several methods of processing the queue (cron, a Drush command, contrib modules, etc.). Each method follows the same steps: "grab" a job, process it, and continue until some limit is reached.
So, it shouldn't matter if the queue is already being processed by some other method (or a previous cron run). Each job needs to be independent, and only one processor can grab a given job that is in the queue.
I'd be inclined to mark this as "works as designed".
Comment #2
David_Rothstein commentedWell, maybe not a bug then, but still seems like an issue that we assume/advertise in various places that the poormanscron feature will only result in one unlucky user every X minutes getting a slow page load, when in fact it could result in a whole bunch of them.
The attached patch (completely untested) is what I was thinking of. Actually, if you look at it, it seems like it must be some kind of bug that the existing code for looping through each queue and (re-)creating it only happens when a lock is acquired... but all the other queue processing happens regardless. But I'm not sure if that problem has any actual practical effect.
Comment #3
jhodgdonI think this patch is a good idea. +1. I haven't tested it either, but moving the queue operations inside the cron lock check seems like a good idea. Presumably the maintainers of the cron system will tell us why it was done the other way previously?
Comment #4
Nephele commentedSorry, but I think this is an unnecessary patch that breaks how the system is intended to work. The cron queue is supposed to work differently from standard cron jobs, and moving queue operations inside the cron lock removes one of the key differences. As stated in the cron queue documentation:
Unless this behavior is causing an actual bug (and the bug is not due to a poorly designed queue item), then I don't see why it should be altered. I'm changing to works as designed.
Comment #5
slip commentedSorry but 6 years later this bug just bit me on a site I'm maintaining and it has nothing to do with a poorly designed queue. The issue is Drupal's automated_cron is set to keep calling cron over and over again on every page load. If you have a long running queue (1 minute say) and you have a lot of traffic, you can easily max out your servers with tons of queues running simultaneously causing the site to crash.
As this is a standard setup we should provide more protection. If the developer wants their queues to be scheduled to run on top of each other, they could easily find other solutions that are more reasonably configured.
I'm submitting a 8.7.x patch to move the call into the lock to at least provide some protection.
Comment #15
podarok#13 looks good and fixes an issue
Comment #16
longwaveI agree with #4, queues are designed to be processed in parallel if there is a lot of work to be done.
For sites that need more control over this they should explicitly call cron from an external cron job (instead of relying on the automatic cron that runs after page loads) or use https://www.drupal.org/project/ultimate_cron
Comment #17
catchHmm I also agree with #4 and #16 however I'm not sure it's an argument against making this change.
If you have dedicated jobs to run down queues, putting the cron queue running inside the cron lock won't prevent them running simultaneously, it'll only stop more than one cron run from trying to process the queues at once.
Comment #18
longwaveAfter thinking about this some more, this indeed doesn't harm sites that process queues separately, but it does help the case where cron is run regularly and prevents sites with occasionally-busy queues from running out of resources and trying to process more than one queue at a time.
Comment #19
alexpottRunning tests against 9.5.x and 10.1.x...
I debated the need for a CR but I think the fact that the warning
$this->logger->warning('Attempting to re-run cron while it is already running.');exists means that people should not be depending on the current behaviour - as they'd be getting loads of warnings.I've credited everyone who contributed to the discussion even if they thought it was works as designed.
Comment #20
alexpottRemoving credit for @pmagunia - the patch in #5 still applies to 10.x and 9.x so a new MR was unnecessary.
Comment #21
catch10.1 failure is real.
Comment #22
longwaveThe cron unit test needed some updating to match the new behaviour.
Comment #24
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Tested on 10.1.x with a standard install
Applied patch and verified cron still runs from the UI and from an external URL
But think the tests need tweaking. I applied the test changes and removed the update to Cron.php and the tests still pass.
Comment #25
longwaveThe tests should still pass; however they made assumptions before that are now incorrect if we only update \Drupal\Core\Cron, so the test needed some tweaking in order for it to pass again (see the fail in #5).
Comment #26
smustgrave commentedAh thank you for that explanation. In that case the changes look good to me.
Comment #28
catchCommitted/pushed to 10.1.x, cherry-picked to 10.0.x and 9.5.x, thanks!
Comment #31
wim leersTangentially related: #3318964: automated_cron should not run cron when visiting update.php — that's s another way that cron gets executed but shouldn't. 😅