WordPress.org

Make WordPress Core

Opened 2 years ago

Closed 2 years ago

Last modified 7 months ago

#23405 closed defect (bug) (fixed)

blog-details cache can get stuck with bad value

Reported by: westi Owned by: ryan
Milestone: 3.6 Priority: normal
Severity: normal Version: 3.5.1
Component: Multisite Keywords: has-patch
Focuses: Cc:

Description (last modified by westi)

If you call get_blog_details for a blog which doesn't exist yet in wp_blogs then we cache a negative lookup result as -1:

https://core.trac.wordpress.org/browser/trunk/wp-includes/ms-blogs.php?rev=23389#L217

        if ( empty($details) ) {
                $details = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE blog_id = %d /* get_blog_details */", $blog_id ) );
                if ( ! $details ) {
                        // Set the full cache.
                        wp_cache_set( $blog_id, -1, 'blog-details' );
                        return false;
                }
        }

When you then later call refresh_blog_details to clear up the cache for the blog_id the cached -1 is passed to clean_blog_cache which then tries to get a blog_id from the object that was returned and doesn't get the right one and the cached are not deleted.

This means that the blog ends up broken :(

Attachments (3)

23405-01.patch (498 bytes) - added by beezeee 2 years ago.
Force clearing 'blog-details' cache in refresh_blog_details if no details returned from first call to get_blog_details
23405.diff (505 bytes) - added by hirozed 2 years ago.
23405.2.diff (504 bytes) - added by hirozed 2 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 @westi2 years ago

  • Description modified (diff)

comment:2 @nacin2 years ago

  • Milestone changed from Awaiting Review to 3.6

@beezeee2 years ago

Force clearing 'blog-details' cache in refresh_blog_details if no details returned from first call to get_blog_details

comment:3 @beezeee2 years ago

  • Keywords has-patch added; needs-patch removed

The above patch seems to do the job, the test below confirms:

<?php

require_once('./wp-load.php');
global $wpdb;
$next_id = $wpdb->get_var(
    "SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = '".DB_NAME."' "
    ." AND TABLE_NAME = '{$wpdb->blogs}'"
);
echo '<pre>';
echo "Next blog id to be added $next_id \n\n";
echo "get_blog_details(1): \n\n";
echo var_export(get_blog_details(1))."\n\n";
echo "get_blog_details($next_id): \n";
echo var_export(get_blog_details($next_id))."\n\n";
$new_blog = wpmu_create_blog(get_bloginfo('domain'), 'secondblog', 'Second Blog',
                    1);
echo "added blog $new_blog and refresh_blog_details($new_blog) \n\n";
refresh_blog_details($new_blog);
echo "get_blog_details($next_id) \n\n";
echo var_export(get_blog_details($next_id))."\n\n";
echo "cleaning up \n\n";
wpmu_delete_blog($new_blog, true);
echo '</pre>';

@hirozed2 years ago

@hirozed2 years ago

comment:4 @hirozed2 years ago

  • Cc hirozed added

The above patch (the .2 version) checks for the result of -1 from $details and passes null for domain and path, which should satisfy clean_blog_cache.

comment:5 @ryan2 years ago

Version 0, edited 2 years ago by ryan (next)

comment:6 @ryan2 years ago

  • Owner set to ryan
  • Resolution set to fixed
  • Status changed from new to closed

In 23752:

In refresh_blog_details(), make sure clean_blog_cache() gets the blog ID when the blog has been previously cached as non-existent. This ensures that -1 values in blog-details are cleared after blogs are created.

Props beezeee, hirozed
fixes #23405

comment:7 @jeremyfelt7 months ago

In 30175:

Improve layout of test for cached invalid, then valid site details

  • Rename method to test_get_blog_details_when_site_does_not_exist().
  • Always assume MAX(blog_id) is 1 and therefore always create a burner.
  • Remove tests specific to wpmu_delete_blog() and cache, to be handled elsewhere.
  • Remove extra asertions.

See #30080, #23405

Note: See TracTickets for help on using tickets.