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 ) );
    }