I saved in my startup bookmarks two report pages of my site ("Recent hits" and "Top referrers"). When I open the startup bookmarks in my browser, I often see a bunch of "Duplicate entry..." errors in system.module, line #821. This query is in function system_theme_data() and it's invoked by function update_get_projects() when the project cache is expired.
I guess this happens when two instances of update_get_projects() are running at the same time: both instances find an expired cache, the first one writes the records in the system table, the second one fails on each insert query.
The execution of function update_get_projects() should be locked (see the cron sempahore) to prevent multiple instances of project cache refresh.

CommentFileSizeAuthor
#2 363893-update-lock-D7.patch1.96 KBDave Reid
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dww’s picture

Title: Lock execution of function update_get_projects() » Lock execution of update_get_projects() and _update_refresh()
Version: 6.9 » 7.x-dev
Priority: Minor » Normal
Dave Reid’s picture

Status: Active » Needs review
FileSize
1.96 KB

Locking framework is added in core. Patch attached for review.

dww’s picture

Seems to work with my local testing. Patch looks fine.

My only concern is propagating errors nicely when we fail to acquire a lock. If you're viewing the available updates report, and open "check manually" twice into new tabs at the same time, one of them just gives you the error message: "Unable to fetch any information about available new releases and updates." and the other works. Perhaps we want to propagate failure to acquire a lock differently?

I'm not entirely sure the best way to write a test for this case, either... Any suggestions on that would be appreciated.

Dries’s picture

It would be useful to see the actual error message, IMO. It would me understand the problem while reviewing this patch.

dww’s picture

Status: Needs review » Needs work

Looks like this needs to be reworked to propagate errors more clearly.

catch’s picture

For the failure to acquire the lock, we should do lock_wait() - the second tab then has to wait for the first to get the data before it shows anything, which is fine, 'cos that's probably less time than it would've taken anyway.

Then the question is what happens if lock_wait() returns after 30 seconds and there's still no cached data - that's under debate in other issues as well.

dww’s picture

Since this issue was last considered, we managed to get #597484: Use the Queue API to fetch available update data in core. So, now that I think about it, it's not clear we should lock _update_refresh(). Really, it'd be *good* to have multiple threads draining that queue. ;) What we need to lock is update_get_projects(), and the parts of the logic that put tasks into the fetch queue...

Eventually, we want to move away from big expensive functions that we're trying to lock execution of. See #238950: Meta: update.module RAM consumption. Since the release history of separate projects can't influence the status of each other (except for themes and base themes), eventually it'd be great to queue-ify update_calculate_project_data() and parallelize that, instead of trying to lock the whole thing and do it all in one page load. We're already storing the available release history for each project in separate cids in {cache_update}. It'd be good if we did a similar thing for the status of each project instead of stuffing it all into a giant 'update_project_data' entry. And when we notice a condition that makes us want to recompute status, we just try to do it on project at a time. The available update report could be smarter about showing different things for each project like "status unknown", "fetching information about available releases", "computing status", whatever. That's basically the end goal for #238950...

So, to the extent we're going to add any locking, we should be careful not to make any of these other efforts harder to accomplish.

Status: Needs work » Needs review

ebpo queued 2: 363893-update-lock-D7.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 2: 363893-update-lock-D7.patch, failed testing.