message_cron() calls message_get_purgeable_by_type() with the following:
$purge_messages += message_get_purgeable_by_type(...)
This is called multiple times, with $purge_limit being reduced as results are returned. However, the return if $purge_limit ever gets to zero is:
function message_get_purgeable_by_type(&$purge_limit, $message_type_name, $purge_settings) {
if ($purge_limit <= 0) {
return;
}
This causes a fatal error, killing the cron and preventing anything subsequent (including all queue processing) to never run.