ezpContentPublishingQueueProcessor::terminate(); @unlink($pidFile); eZScript::instance()->shutdown(0); break; } }; pcntl_signal(SIGTERM, $daemonSignalHandler); pcntl_signal(SIGINT, $daemonSignalHandler); if ($options['daemon']) { // Trap signals that we expect to recieve pcntl_signal(SIGCHLD, 'childHandler'); pcntl_signal(SIGUSR1, 'childHandler'); pcntl_signal(SIGALRM, 'childHandler'); // close the PID file, and reopen it after forking fclose($pidFp); eZClusterFileHandler::preFork(); $pid = pcntl_fork(); if ($pid < 0) { error_log("unable to fork daemon"); $script->shutdown(1, "unable to fork daemon"); } // If we got a good PID, then we can wait until the daemon tells us to terminate if ($pid > 0) { // Wait for confirmation from the child via SIGTERM or SIGCHLD, or // for two seconds to elapse (SIGALRM). pause() should not return. */ sleep(10); $script->shutdown(1, "Failed spawning the daemon process"); } $pidFp = fopen($pidFile, 'w'); flock($pidFp, LOCK_EX | LOCK_NB); // At this point we are executing as the child process
/** * Starts the publishing process for the linked version. After publishing, * the child process is terminated. * * @return false|int false if the fork fails, the pid of the child process * after the fork */ public function publish() { $contentObjectId = $this->version()->attribute('contentobject_id'); $contentObjectVersion = $this->version()->attribute('version'); // $processObject = ezpContentPublishingProcess::fetchByContentObjectVersion( $contentObjectId, $contentObjectVersion ); $this->setStatus(self::STATUS_WORKING, true, "beginning publishing"); // prepare the cluster file handler for the fork eZClusterFileHandler::preFork(); $pid = pcntl_fork(); // force the DB connection closed $db = eZDB::instance(); $db->close(); $db = null; eZDB::setInstance(null); // Force the new stack DB connection closed as well try { $kernel = ezpKernel::instance(); if ($kernel->hasServiceContainer()) { $serviceContainer = $kernel->getServiceContainer(); $dbHandler = $serviceContainer->get('ezpublish.connection'); $factory = $serviceContainer->get('ezpublish.api.storage_engine.legacy.dbhandler.factory'); $dbHandler->setDbHandler($factory->buildLegacyDbHandler()->getDbHandler()); } } catch (LogicException $e) { // we just ignore this, since it means that we are running in a pure legacy context } // Force the cluster DB connection closed if the cluster handler is DB based $cluster = eZClusterFileHandler::instance(); // error, cancel if ($pid == -1) { $this->setStatus(self::STATUS_PENDING, true, "pcntl_fork() failed"); return false; } else { if ($pid) { return $pid; } } // child process try { $myPid = getmypid(); pcntl_signal(SIGCHLD, SIG_IGN); $this->setAttribute('pid', $myPid); $this->setAttribute('started', time()); $this->store(array('pid', 'started')); // login the version's creator to make sure publishing happens as if ran synchronously $creatorId = $this->version()->attribute('creator_id'); $creator = eZUser::fetch($creatorId); eZUser::setCurrentlyLoggedInUser($creator, $creatorId); unset($creator, $creatorId); $operationResult = eZOperationHandler::execute('content', 'publish', array('object_id' => $contentObjectId, 'version' => $contentObjectVersion)); // Statuses other than CONTINUE require special handling if ($operationResult['status'] != eZModuleOperationInfo::STATUS_CONTINUE) { if ($operationResult['status'] == eZModuleOperationInfo::STATUS_HALTED) { // deferred to crontab if (strpos($operationResult['result']['content'], 'Deffered to cron') !== false) { $processStatus = self::STATUS_DEFERRED; } else { $processStatus = self::STATUS_UNKNOWN; } } else { $processStatus = self::STATUS_UNKNOWN; } } else { $processStatus = self::STATUS_FINISHED; } // mark the process as completed $this->setAttribute('pid', 0); $this->setStatus($processStatus, false, "publishing operation finished"); $this->setAttribute('finished', time()); $this->store(array('status', 'finished', 'pid')); // Call the postProcessing hook ezpContentPublishingQueue::signals()->emit('postHandling', $contentObjectId, $contentObjectVersion, $processStatus); } catch (eZDBException $e) { $this->reset("database error: " . $e->getMessage()); } // generate static cache $ini = eZINI::instance(); if ($ini->variable('ContentSettings', 'StaticCache') == 'enabled') { $staticCacheHandlerClassName = $ini->variable('ContentSettings', 'StaticCacheHandler'); $staticCacheHandlerClassName::executeActions(); } eZScript::instance()->shutdown(); exit; }
/** * Fork and execute * * @param int $nodeid * @param int $offset * @param int $limit */ protected function forkAndExecute($nodeID, $offset, $limit) { eZDB::setInstance(null); // Prepare DB-based cluster handler for fork (it will re-connect DB automatically). eZClusterFileHandler::preFork(); $pid = pcntl_fork(); // reinitialize DB after fork $this->initializeDB(); if ($pid == -1) { die('could not fork'); } else { if ($pid) { // Main process return $pid; } else { // We are the child process if ($this->execute($nodeID, $offset, $limit) > 0) { $this->Script->shutdown(0); } else { $this->Script->shutdown(3); } } } }
/** * Starts the publishing process for the linked version. After publishing, * the child process is terminated. * * @return false|int false if the fork fails, the pid of the child process * after the fork */ public function publish() { $contentObjectId = $this->version()->attribute('contentobject_id'); $contentObjectVersion = $this->version()->attribute('version'); // $processObject = ezpContentPublishingProcess::fetchByContentObjectVersion( $contentObjectId, $contentObjectVersion ); $this->setAttribute('status', self::STATUS_WORKING); $this->store(array('status')); // prepare the cluster file handler for the fork eZClusterFileHandler::preFork(); $pid = pcntl_fork(); // force the DB connection closed $db = eZDB::instance(); $db->close(); $db = null; eZDB::setInstance(null); // Force the cluster DB connection closed if the cluster handler is DB based $cluster = eZClusterFileHandler::instance(); // error, cancel if ($pid == -1) { $this->setAttribute('status', self::STATUS_PENDING); $this->store(array('status')); return false; } else { if ($pid) { return $pid; } } // child process try { $myPid = getmypid(); pcntl_signal(SIGCHLD, SIG_IGN); $this->setAttribute('pid', $myPid); $this->setAttribute('started', time()); $this->store(array('pid', 'started')); // login the version's creator to make sure publishing happens as if ran synchronously $creatorId = $this->version()->attribute('creator_id'); $creator = eZUser::fetch($creatorId); eZUser::setCurrentlyLoggedInUser($creator, $creatorId); unset($creator, $creatorId); $operationResult = eZOperationHandler::execute('content', 'publish', array('object_id' => $contentObjectId, 'version' => $contentObjectVersion)); // Statuses other than CONTINUE require special handling if ($operationResult['status'] != eZModuleOperationInfo::STATUS_CONTINUE) { if ($operationResult['status'] == eZModuleOperationInfo::STATUS_HALTED) { // deferred to crontab if (strpos($operationResult['result']['content'], 'Deffered to cron') !== false) { $processStatus = self::STATUS_DEFERRED; } else { $processStatus = self::STATUS_UNKNOWN; } } else { $processStatus = self::STATUS_UNKNOWN; } } else { $processStatus = self::STATUS_FINISHED; } // mark the process as completed $this->setAttribute('pid', 0); $this->setAttribute('status', $processStatus); $this->setAttribute('finished', time()); $this->store(array('status', 'finished', 'pid')); // Call the postProcessing hook ezpContentPublishingQueue::signals()->emit('postHandling', $contentObjectId, $contentObjectVersion, $processStatus); } catch (eZDBException $e) { $this->reset(); } eZScript::instance()->shutdown(); exit; }
/** * Test for the global {@see eZClusterFilehandler::preFork()} method */ public function testPreFork() { $handler = eZClusterFileHandler::instance(); $refHandler = new ReflectionObject( $handler ); $refBackendProperty = $refHandler->getProperty( 'dbbackend' ); $refBackendProperty->setAccessible( true ); self::assertNotNull( $refBackendProperty->getValue( $handler ) ); eZClusterFileHandler::preFork(); self::assertNull( $refBackendProperty->getValue( $handler ) ); }