+ /**
+ * Checks if the worker is running in the daemon mode.
+ *
+ * @return boolean
+ */
+ public static function isDaemonMode()
+ {
+ if (!is_null(self::$daemon_mode)) {
+ return self::$daemon_mode;
+ }
+
+ if (DI::mode()->getExecutor() == Mode::DAEMON) {
+ return true;
+ }
+
+ $daemon_mode = DI::config()->get('system', 'worker_daemon_mode', false, true);
+ if ($daemon_mode) {
+ return $daemon_mode;
+ }
+
+ if (!function_exists('pcntl_fork')) {
+ self::$daemon_mode = false;
+ return false;
+ }
+
+ $pidfile = DI::config()->get('system', 'pidfile');
+ if (empty($pidfile)) {
+ // No pid file, no daemon
+ self::$daemon_mode = false;
+ return false;
+ }
+
+ if (!is_readable($pidfile)) {
+ // No pid file. We assume that the daemon had been intentionally stopped.
+ self::$daemon_mode = false;
+ return false;
+ }
+
+ $pid = intval(file_get_contents($pidfile));
+ $running = posix_kill($pid, 0);
+
+ self::$daemon_mode = $running;
+ return $running;
+ }
+
+ /**
+ * Test if the daemon is running. If not, it will be started
+ *
+ * @return void
+ */
+ private static function checkDaemonState()
+ {
+ if (!DI::config()->get('system', 'daemon_watchdog', false)) {
+ return;
+ }
+
+ if (!DI::mode()->isNormal()) {
+ return;
+ }
+
+ // Check every minute if the daemon is running
+ if (DI::config()->get('system', 'last_daemon_check', 0) + 60 > time()) {
+ return;
+ }
+
+ DI::config()->set('system', 'last_daemon_check', time());
+
+ $pidfile = DI::config()->get('system', 'pidfile');
+ if (empty($pidfile)) {
+ // No pid file, no daemon
+ return;
+ }
+
+ if (!is_readable($pidfile)) {
+ // No pid file. We assume that the daemon had been intentionally stopped.
+ return;
+ }
+
+ $pid = intval(file_get_contents($pidfile));
+ if (posix_kill($pid, 0)) {
+ Logger::info('Daemon process is running', ['pid' => $pid]);
+ return;
+ }
+
+ Logger::warning('Daemon process is not running', ['pid' => $pid]);
+
+ self::spawnDaemon();
+ }
+
+ /**
+ * Spawn a new daemon process
+ *
+ * @return void
+ */
+ private static function spawnDaemon()
+ {
+ Logger::notice('Starting new daemon process');
+ $command = 'bin/daemon.php';
+ $a = DI::app();
+ DI::system()->run($command, ['start']);
+ Logger::notice('New daemon process started');
+ }
+