/** * Potentially open a socket and sent an HTTP request back to the server * to run a specified number of jobs. This registers a callback to cleanup * the socket once it's done. */ protected function triggerJobs() { global $wgJobRunRate, $wgServer, $wgRunJobsAsync; if ($wgJobRunRate <= 0 || wfReadOnly()) { return; } elseif ($this->getTitle()->isSpecial('RunJobs')) { return; // recursion guard } $section = new ProfileSection(__METHOD__); if ($wgJobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $wgJobRunRate) { return; // the higher $wgJobRunRate, the less likely we return here } $n = 1; } else { $n = intval($wgJobRunRate); } if (!$wgRunJobsAsync) { // If running jobs asynchronously has been disabled, run the job here // while the user waits SpecialRunJobs::executeJobs($n); return; } if (!JobQueueGroup::singleton()->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) { return; // do not send request if there are probably no jobs } $query = array('title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5); $query['signature'] = SpecialRunJobs::getQuerySignature($query); $errno = $errstr = null; $info = wfParseUrl($wgServer); wfSuppressWarnings(); $sock = fsockopen($info['host'], isset($info['port']) ? $info['port'] : 80, $errno, $errstr, 0.1); wfRestoreWarnings(); if (!$sock) { wfDebugLog('runJobs', "Failed to start cron API (socket error {$errno}): {$errstr}\n"); // Fall back to running the job here while the user waits SpecialRunJobs::executeJobs($n); return; } $url = wfAppendQuery(wfScript('index'), $query); $req = "POST {$url} HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n"; wfDebugLog('runJobs', "Running {$n} job(s) via '{$url}'\n"); // Send a cron API request to be performed in the background. // Give up if this takes too long to send (which should be rare). stream_set_timeout($sock, 1); $bytes = fwrite($sock, $req); if ($bytes !== strlen($req)) { wfDebugLog('runJobs', "Failed to start cron API (socket write error)\n"); } else { // Do not wait for the response (the script should handle client aborts). // Make sure that we don't close before that script reaches ignore_user_abort(). $status = fgets($sock); if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) { wfDebugLog('runJobs', "Failed to start cron API: received '{$status}'\n"); } } fclose($sock); }