| 
									
										
										
										
											2017-12-14 16:38:51 +00:00
										 |  |  | #!/usr/bin/env php
 | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2016-11-27 22:52:21 +00:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-03-19 03:24:09 +00:00
										 |  |  |  * @file bin/daemon.php | 
					
						
							| 
									
										
										
										
											2017-11-19 22:00:43 +00:00
										 |  |  |  * @brief Run the worker from a daemon. | 
					
						
							| 
									
										
										
										
											2016-11-27 22:52:21 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This script was taken from http://php.net/manual/en/function.pcntl-fork.php | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-05 07:02:55 +00:00
										 |  |  | use Dice\Dice; | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | use Friendica\Core\Config; | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | use Friendica\Core\Logger; | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | use Friendica\Core\Worker; | 
					
						
							| 
									
										
										
										
											2018-07-20 12:19:26 +00:00
										 |  |  | use Friendica\Database\DBA; | 
					
						
							| 
									
										
										
										
											2019-12-15 22:52:15 +00:00
										 |  |  | use Friendica\DI; | 
					
						
							| 
									
										
										
										
											2019-09-17 14:47:00 +00:00
										 |  |  | use Psr\Log\LoggerInterface; | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-23 11:40:52 +00:00
										 |  |  | // Get options
 | 
					
						
							| 
									
										
										
										
											2018-07-24 03:42:44 +00:00
										 |  |  | $shortopts = 'f'; | 
					
						
							|  |  |  | $longopts = ['foreground']; | 
					
						
							| 
									
										
										
										
											2018-07-23 11:40:52 +00:00
										 |  |  | $options = getopt($shortopts, $longopts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | // Ensure that daemon.php is executed from the base path of the installation
 | 
					
						
							|  |  |  | if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { | 
					
						
							|  |  |  | 	$directory = dirname($_SERVER["argv"][0]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (substr($directory, 0, 1) != "/") { | 
					
						
							| 
									
										
										
										
											2018-07-22 16:28:39 +00:00
										 |  |  | 		$directory = $_SERVER["PWD"] . "/" . $directory; | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-22 16:28:39 +00:00
										 |  |  | 	$directory = realpath($directory . "/.."); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	chdir($directory); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 14:56:48 +00:00
										 |  |  | require dirname(__DIR__) . '/vendor/autoload.php'; | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-05 07:02:55 +00:00
										 |  |  | $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php'); | 
					
						
							| 
									
										
										
										
											2019-09-17 14:47:00 +00:00
										 |  |  | $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['daemon']]); | 
					
						
							| 
									
										
										
										
											2019-07-20 23:22:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-15 22:52:15 +00:00
										 |  |  | DI::init($dice); | 
					
						
							|  |  |  | $a = DI::app(); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-15 22:52:15 +00:00
										 |  |  | if (DI::mode()->isInstall()) { | 
					
						
							| 
									
										
										
										
											2018-06-26 00:56:07 +00:00
										 |  |  | 	die("Friendica isn't properly installed yet.\n"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Config::load(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-26 00:56:35 +00:00
										 |  |  | if (empty(Config::get('system', 'pidfile'))) { | 
					
						
							| 
									
										
										
										
											2018-11-25 06:44:51 +00:00
										 |  |  | 	die(<<<TXT | 
					
						
							|  |  |  | Please set system.pidfile in config/local.config.php. For example: | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     'system' => [  | 
					
						
							|  |  |  |         'pidfile' => '/path/to/daemon.pid', | 
					
						
							|  |  |  |     ], | 
					
						
							|  |  |  | TXT | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-26 00:56:35 +00:00
										 |  |  | $pidfile = Config::get('system', 'pidfile'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | if (in_array("start", $_SERVER["argv"])) { | 
					
						
							|  |  |  | 	$mode = "start"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if (in_array("stop", $_SERVER["argv"])) { | 
					
						
							|  |  |  | 	$mode = "stop"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if (in_array("status", $_SERVER["argv"])) { | 
					
						
							|  |  |  | 	$mode = "status"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-23 11:40:52 +00:00
										 |  |  | $foreground = array_key_exists('f', $options) || array_key_exists('foreground', $options); | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | if (!isset($mode)) { | 
					
						
							|  |  |  | 	die("Please use either 'start', 'stop' or 'status'.\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-14 16:38:51 +00:00
										 |  |  | if (empty($_SERVER["argv"][0])) { | 
					
						
							|  |  |  | 	die("Unexpected script behaviour. This message should never occur.\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 16:28:39 +00:00
										 |  |  | $pid = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if (is_readable($pidfile)) { | 
					
						
							|  |  |  | 	$pid = intval(file_get_contents($pidfile)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-14 16:38:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | if (empty($pid) && in_array($mode, ["stop", "status"])) { | 
					
						
							|  |  |  | 	Config::set('system', 'worker_daemon_mode', false); | 
					
						
							|  |  |  | 	die("Pidfile wasn't found. Is the daemon running?\n"); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if ($mode == "status") { | 
					
						
							|  |  |  | 	if (posix_kill($pid, 0)) { | 
					
						
							|  |  |  | 		die("Daemon process $pid is running.\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unlink($pidfile); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 	Config::set('system', 'worker_daemon_mode', false); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 	die("Daemon process $pid isn't running.\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if ($mode == "stop") { | 
					
						
							|  |  |  | 	posix_kill($pid, SIGTERM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unlink($pidfile); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | 	Logger::notice("Worker daemon process was killed", ["pid" => $pid]); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Config::set('system', 'worker_daemon_mode', false); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 	die("Worker daemon process $pid was killed.\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | if (!empty($pid) && posix_kill($pid, 0)) { | 
					
						
							|  |  |  | 	die("Daemon process $pid is already running.\n"); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | Logger::notice('Starting worker daemon.', ["pid" => $pid]); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | if (!$foreground) { | 
					
						
							|  |  |  | 	echo "Starting worker daemon.\n"; | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	// Switch over to daemon mode.
 | 
					
						
							|  |  |  | 	if ($pid = pcntl_fork()) { | 
					
						
							|  |  |  | 		return;     // Parent
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	fclose(STDIN);  // Close all of the standard
 | 
					
						
							| 
									
										
										
										
											2018-07-11 06:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Enabling this seem to block a running php process with 100% CPU usage when there is an outpout
 | 
					
						
							|  |  |  | 	// fclose(STDOUT); // file descriptors as we
 | 
					
						
							|  |  |  | 	// fclose(STDERR); // are running as a daemon.
 | 
					
						
							| 
									
										
										
										
											2018-06-10 22:04:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 12:19:26 +00:00
										 |  |  | 	DBA::disconnect(); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	register_shutdown_function('shutdown'); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	if (posix_setsid() < 0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ($pid = pcntl_fork()) { | 
					
						
							|  |  |  | 		return;     // Parent
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	$pid = getmypid(); | 
					
						
							|  |  |  | 	file_put_contents($pidfile, $pid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We lose the database connection upon forking
 | 
					
						
							| 
									
										
										
										
											2019-07-21 18:24:16 +00:00
										 |  |  | 	DBA::reconnect(); | 
					
						
							| 
									
										
										
										
											2018-06-10 22:04:09 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | Config::set('system', 'worker_daemon_mode', true); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | // Just to be sure that this script really runs endlessly
 | 
					
						
							|  |  |  | set_time_limit(0); | 
					
						
							| 
									
										
										
										
											2017-12-14 16:38:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | $wait_interval = intval(Config::get('system', 'cron_interval', 5)) * 60; | 
					
						
							| 
									
										
										
										
											2017-12-14 16:38:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | $do_cron = true; | 
					
						
							| 
									
										
										
										
											2018-06-06 05:26:22 +00:00
										 |  |  | $last_cron = 0; | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | // Now running as a daemon.
 | 
					
						
							|  |  |  | while (true) { | 
					
						
							| 
									
										
										
										
											2018-06-06 05:26:22 +00:00
										 |  |  | 	if (!$do_cron && ($last_cron + $wait_interval) < time()) { | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | 		Logger::info('Forcing cron worker call.', ["pid" => $pid]); | 
					
						
							| 
									
										
										
										
											2018-06-06 05:26:22 +00:00
										 |  |  | 		$do_cron = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 	Worker::spawnWorker($do_cron); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 05:26:22 +00:00
										 |  |  | 	if ($do_cron) { | 
					
						
							| 
									
										
										
										
											2018-06-11 03:45:45 +00:00
										 |  |  | 		// We force a reconnect of the database connection.
 | 
					
						
							| 
									
										
										
										
											2018-06-10 22:04:09 +00:00
										 |  |  | 		// This is done to ensure that the connection don't get lost over time.
 | 
					
						
							| 
									
										
										
										
											2018-07-20 12:19:26 +00:00
										 |  |  | 		DBA::reconnect(); | 
					
						
							| 
									
										
										
										
											2018-06-10 22:04:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 05:26:22 +00:00
										 |  |  | 		$last_cron = time(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | 	Logger::info("Sleeping", ["pid" => $pid]); | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	$start = time(); | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 		$seconds = (time() - $start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// logarithmic wait time calculation.
 | 
					
						
							|  |  |  | 		// Background: After jobs had been started, they often fork many workers.
 | 
					
						
							|  |  |  | 		// To not waste too much time, the sleep period increases.
 | 
					
						
							|  |  |  | 		$arg = (($seconds + 1) / ($wait_interval / 9)) + 1; | 
					
						
							|  |  |  | 		$sleep = round(log10($arg) * 1000000, 0); | 
					
						
							|  |  |  | 		usleep($sleep); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		$timeout = ($seconds >= $wait_interval); | 
					
						
							|  |  |  | 	} while (!$timeout && !Worker::IPCJobsExists()); | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 18:18:20 +00:00
										 |  |  | 	if ($timeout) { | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 		$do_cron = true; | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | 		Logger::info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]); | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		$do_cron = false; | 
					
						
							| 
									
										
										
										
											2019-02-12 19:12:25 +00:00
										 |  |  | 		Logger::info("Worker jobs are calling to be forked.", ["pid" => $pid]); | 
					
						
							| 
									
										
										
										
											2018-06-06 03:48:04 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 22:09:27 +00:00
										 |  |  | function shutdown() { | 
					
						
							|  |  |  | 	posix_kill(posix_getpid(), SIGHUP); | 
					
						
							| 
									
										
										
										
											2016-11-27 20:57:18 +00:00
										 |  |  | } |