[李景山php]每天TP5-20170126|thinkphp5-Process.php-8

    /**
     * 創建所需的 proc_open 的描述符
     * @return array
     */
    private function getDescriptors()
    {// 獲取描述符
        if ('\\' === DS) {// 如果是windows
            $this->processPipes = WindowsPipes::create($this, $this->input);// 創建 windows 管道系統
        } else {
            $this->processPipes = UnixPipes::create($this, $this->input);// 創建 unix 管道系統
        }
        $descriptors = $this->processPipes->getDescriptors($this->outputDisabled);// 獲取描述信息

        if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {

            $descriptors = array_merge($descriptors, [['pipe', 'w']]);// 如果滿足上述 的全部條件

            $this->commandline = '(' . $this->commandline . ') 3>/dev/null; code=$?; echo $code >&3; exit $code';
        }// 進行 命令行設置

        return $descriptors;// 返回描述,並且 執行 命令行工具
    }

    /**
     * 建立 wait () 使用的回調。
     * @param callable|null $callback
     * @return callable
     */
    protected function buildCallback($callback)
    {// wait 使用回調 建立 回調函數
        $out      = self::OUT;// 輸出
        $callback = function ($type, $data) use ($callback, $out) {// 回調函數
            // 閉包 用法
            // 很經典的一個用法
            if ($out == $type) {// 如果 可以輸出
                $this->addOutput($data);
            } else {// 否則添加錯誤數據
                $this->addErrorOutput($data);
            }

            if (null !== $callback) {// 回調
                call_user_func($callback, $type, $data);
            }
        };

        return $callback;// 返回一個回調函數
    }

    /**
     * 更新狀態
     * @param bool $blocking
     */
    protected function updateStatus($blocking)
    {// 更新狀態
        if (self::STATUS_STARTED !== $this->status) {// 當前狀態不是啓動狀態 工作狀態
            return;
        }// 如果狀態不對,直接返回

        $this->processInformation = proc_get_status($this->process);// 獲取進程狀態信息
        $this->captureExitCode();// 獲取執行代碼

        $this->readPipes($blocking, '\\' === DS ? !$this->processInformation['running'] : true);// 讀取管道信息

        if (!$this->processInformation['running']) {//如果當前信息 沒有運行中
            $this->close();// 關閉
        }
    }// 在經歷了3次外包之後,基本上就 沒有 那個東西了是可以被看見的了

    /**
     * 是否開啓 '--enable-sigchild'
     * @return bool
     */
    protected function isSigchildEnabled()
    {
        if (null !== self::$sigchild) {// 返回默認狀態
            return self::$sigchild;
        }

        if (!function_exists('phpinfo')) {// 如果沒有 phpinfo 這個函數
            return self::$sigchild = false;
        }

        ob_start();// 開啓緩存
        phpinfo(INFO_GENERAL);// 信息 啓動

        return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');// 很神奇的判斷方式
    }

    /**
     * 驗證是否超時
     * @param int|float|null $timeout
     * @return float|null
     */
    private function validateTimeout($timeout)
    {// 驗證是否超時
        $timeout = (float)$timeout;// 設置時間

        if (0.0 === $timeout) {// 如果 爲0
            $timeout = null;// 時間爲空
        } elseif ($timeout < 0) {// 如果時間 小於0 異常
            throw new \InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        return $timeout;
    }

    /**
     * 讀取pipes
     * @param bool $blocking
     * @param bool $close
     */
    private function readPipes($blocking, $close)
    {
        $result = $this->processPipes->readAndWrite($blocking, $close);// 讀寫數據

        $callback = $this->callback;// 回調
        foreach ($result as $type => $data) {// 對返回數據進行 處理
            if (3 == $type) {// 數據類型,返回錯誤代碼
                $this->fallbackExitcode = (int)$data;
            } else {
                $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
            }
        }
    }

    /**
     * 捕獲退出碼
     */
    private function captureExitCode()
    {// 捕獲退出碼
        if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
            $this->exitcode = $this->processInformation['exitcode'];
        }
    }// 將系統運行命令的退出碼,放到系統配置項裏面

    /**
     * 關閉資源
     * @return int 退出碼
     */
    private function close()
    {// 執行 資源 關閉
        $this->processPipes->close();// 關閉資源
        if (is_resource($this->process)) {// 是否有資源
            $exitcode = proc_close($this->process);// 執行進程關閉函數
        } else {
            $exitcode = -1;// 否則 退出碼爲1
        }

        $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
        $this->status   = self::STATUS_TERMINATED;
        // 退出碼
        // 當前狀態

        if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
            $this->exitcode = $this->fallbackExitcode;
        } elseif (-1 === $this->exitcode && $this->processInformation['signaled']
                  && 0 < $this->processInformation['termsig']
        ) {
            $this->exitcode = 128 + $this->processInformation['termsig'];
        }// 是否正常終止,還是異常中斷

        return $this->exitcode;// 返回退出碼
    }

    /**
     * 重置數據
     */
    private function resetProcessData()
    {// 重置全部數據
        $this->starttime                    = null;
        $this->callback                     = null;
        $this->exitcode                     = null;
        $this->fallbackExitcode             = null;
        $this->processInformation           = null;
        $this->stdout                       = null;
        $this->stderr                       = null;
        $this->process                      = null;
        $this->latestSignal                 = null;
        $this->status                       = self::STATUS_READY;
        $this->incrementalOutputOffset      = 0;
        $this->incrementalErrorOutputOffset = 0;
    }

    /**
     * 將一個 POSIX 信號發送到進程中。
     * @param int  $signal
     * @param bool $throwException
     * @return bool
     */
    private function doSignal($signal, $throwException)
    {// 信號發送到進程中
        if (!$this->isRunning()) {
            if ($throwException) {// 拋出異常

                throw new \LogicException('Can not send signal on a non running process.');
            }

            return false;
        }

        if ($this->isSigchildEnabled()) {
            if ($throwException) {
                throw new \RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
            }// 是否 子進程

            return false;
        }

        if (true !== @proc_terminate($this->process, $signal)) {
            if ($throwException) {
                throw new \RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
            }// 進程 中斷

            return false;
        }

        $this->latestSignal = $signal;
// 最終 信號
        return true;// 返回值
    }

    /**
     * 確保進程已經開啓
     * @param string $functionName
     */
    private function requireProcessIsStarted($functionName)
    {// 確認進程開啓
        if (!$this->isStarted()) {
            throw new \LogicException(sprintf('Process must be started before calling %s.', $functionName));
        }
    }

    /**
     * 確保進程已經終止
     * @param string $functionName
     */
    private function requireProcessIsTerminated($functionName)
    {// 確認進程關閉
        if (!$this->isTerminated()) {
            throw new \LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章