/** * Starts the thread. * @return bool On successful execution returns true otherwise returns false. */ public final function start() { // {{{ if (!$this->amIParent()) { return false; } if ($this->amIStarted) { return false; } $this->childPid = pcntl_fork(); if ($this->childPid == -1) { return false; } $this->_childPid = getmypid(); $this->amIStarted = true; $csInitializationResult = null; if ($this->criticalSection !== null) { $csInitializationResult = $this->criticalSection->initialize($this->childPid, $this->uniqueId); } if (!$this->amIParent()) { // child // no dispatchers needed in the children; this means that no threads withing threads creation is possible unregister_tick_function('GPhpThreadCriticalSection::dispatch'); // flag any subscribed variables indicating that the current // instance is located in a GPhpThread foreach (self::$originDynamicDataArr as &$o) { if ($o instanceof \GPhpThreadNotCloneableContainer) { $o->import(true); } } if ($csInitializationResult === false) { $this->stop(); } // don't execute the thread body if critical section is required, but missing pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD)); $this->run(); if ($this->criticalSection !== null) { $this->notifyParentThatChildIsTerminated(); } $this->stop(); } else { // parent if ($this->childPid != -1 && $this->criticalSection !== null) { if ($csInitializationResult === false) { // don't add the thread to the dispatch queue if missing but required critical section is the case (actually this is done in the initialize method above) $this->childPid = -1; $this->_childPid = null; $this->amIStarted = false; return false; } if (!GPhpThread::$isCriticalSectionDispatcherRegistered) { GPhpThread::$isCriticalSectionDispatcherRegistered = register_tick_function('GPhpThreadCriticalSection::dispatch'); } pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD)); // SIGCHLD will wait in the queue until it's processed } return true; } return true; }