Yesterday, attempts to access this site became so slow that they timed out, even though the traffic was nothing exceptional. php5-fpm seemed to be consuming an enormous amount of CPU, so I tried tracing around there. But reading the trace did not immediately reveal anything. To begin with, the dump gets cut off partway through with “dump failed.” There is also information suggesting that the slow log cannot be trusted1.

The log looks like this.

[06-Jan-2016 12:56:04]  [pool www] pid 4835

script_filename = /var/www/index.php

[0x00007ff1e09ae330] unserialize() /var/www/wp-includes/functions.php:319

[0x00007ff1e09ae188] maybe_unserialize() /var/www/wp-includes/option.php:133

[0x00007ff1e09ae088] get_option() /var/www/wp-includes/cron.php:438

[0x00007ff1e09adf40] _get_cron_array() /var/www/wp-includes/cron.php:223

[0x00007ff1e09addd0] wp_next_scheduled() /var/www/wp-includes/update.php:649

[0x00007ffec1ff3ba0] wp_schedule_update_checks() unknown:0

[0x00007ff1e09adbf8] call_user_func_array() /var/www/wp-includes/plugin.php:525

[0x00007ff1e09ada58] do_action() /var/www/wp-settings.php:392

[0x00007ff1e09ad930] +++ dump failed

Various versions of this appear.

In the end, a plugin called SNS Count Cache that I had installed the previous day had created a huge Cron entry, and that was consuming the CPU2.

That aside, how could I improve the situation? By this point, I could not even access the administration screen. I could not delete the plugin from there either.

After trying various things, what ultimately worked was:

  1. Stop php5-fpm. (It must be killed from the command line; under these conditions, service php5-fpm stop alone will not terminate it.)
  2. Stop Apache. (service apache2 stop)
  3. Create a .maintenance file in the WP directory. (This prevents WordPress from running even after Apache and php5-fpm are started.)
  4. Using phpMyAdmin or similar, delete the row with option_id = 102 and option_name=’cron’ from the wp_options table. (This record should have become enormous.)
  5. Immediately create a record with option_id = 102, option_name=’cron’, and auto_id=’yes’.
  6. Go to the WP plugins screen, deactivate the SNS Count Chache plugin, and delete it.
  7. Delete .maintenance.

Disable WordPress’s built-in cron function

While at it, it is even better to disable wp-cron itself and use Linux cron instead. To do that:

  1. In wp-config.php, insert “define(‘DISABLE_WP_CRON’, ‘true’);” on the line after “define(‘DB_COLLATE’, ”);”. In other words:
    define('DB_COLLATE', '');
    define('DISABLE_WP_CRON', 'true');
    

    It should look something like this. This prevents wp-cron.php from being launched every time WP is accessed.

  2. However, simply preventing it from launching is not enough. wp-cron.php must be launched at reasonable intervals. Running it every few hours should be about right. To do this, the launch command must be registered in www-data’s crontab.
    The syntax for launching crontab is as follows.

    sudo crontab -u www-data -e

    This opens an editor, where you register the following.

    0 */6 * * *    cd $wordpress_dir; /usr/bin/php -q wp-cron.php

    (The above is configured to run every 6 hours. Replace $worpdress_dir with the full path to the actual folder.)

    Well then.

 

Footnotes

  1. http://kaiwangchen.github.io/2012/10/04/fpm-slowlog-sucks.html
  2. It took an incredibly long time to figure this out. Once I knew, rereading the log made me think, “Oh, of course,” but….

Related posts

WordPress Customization Notes

I modified my WordPress settings for the first time in a while. I ran into several snags in the process, so here are some notes. Links…

IT · 2016-01-05