Я столкнулся с довольно странным поведением с завитом
Похоже, что это ошибка в связанном с libcurl вопросе, и у автора ответа есть работа для него .
Мои вопросы:
$ch = curl_init('https://www.google.ca/'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // true curl_close($ch); $pid = pcntl_fork(); if ($pid === 0) { $ch = curl_init('http://www.google.ca/'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // true curl_close($ch); $ch = curl_init('https://www.google.ca/'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // false $errno = curl_errno($ch); // 35 $error = curl_error($ch); // SSL connect error curl_close($ch); } else if ($pid > 0) { // wait for child process pcntl_wait($status); } else { // handel fork error }
Если это не ошибка с libcurl, и это то, что я делаю неправильно, пожалуйста, дайте мне знать.
Я просто решил это, используя функцию pcntl_exec . Таким образом, вы существенно удалите свой дочерний код и поместите его в другой файл php, который затем будет выполнен (и фактически заменяет) дочерний процесс.
$ch = curl_init('https://www.google.ca/'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // true curl_close($ch); $pid = pcntl_fork(); if ($pid === 0) { pcntl_exec('child_curl.php'); } else if ($pid > 0) { // wait for child process pcntl_wait($status); } else { // handel fork error }
Содержание child_curl.php:
$ch = curl_init('http://www.google.ca/'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // true curl_close($ch); $ch = curl_init('https://www.google.ca/'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // false $errno = curl_errno($ch); // 35 $error = curl_error($ch); // SSL connect error curl_close($ch);
После выполнения ребенка вы не увидите ошибку.
Эти другие вопросы помогли мне:
Другим обходным решением является использование сокетов.
function fetch_page($url) { $socketPair = array(); if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $socketPair) === false) { return false; } $pid = pcntl_fork(); if ($pid === 0) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $content = curl_exec($ch); curl_close($ch); socket_close($socketPair[1]); socket_set_nonblock($socketPair[0]); $exitStatus = $content ? 0 : 1; if ($content) { while ((strlen($content) > 0) && ($wrote = socket_write($socketPair[0], $content))) { $content = substr($content, $wrote); } } socket_close($socketPair[0]); exit($exitStatus); } else if ($pid > 0) { pcntl_wait($status); socket_close($socketPair[0]); $content = false; if (pcntl_wexitstatus($status) === 0) { $content = ''; while ($line = socket_read($socketPair[1], 4096)) { $len = strlen($content); $content .= $line; } } socket_close($socketPair[1]); return $content; } socket_close($socketPair[0]); socket_close($socketPair[1]); return false; }
Я не нашел способ напрямую разобраться с проблемой, выровненной в вопросе. Однако я разработал пару обходных решений. Оба решения проблемы с процессом fork с (догадываются) другой вилкой.
Обратите внимание: это не предназначено для какого-либо улучшения производительности. Это просто обходное решение проблемы, выделенной в вопросе.
function fetch_page($page) { $tmp_file = tempnam(sys_get_temp_dir(), 'curl_tmp_file'); $pid = pcntl_fork(); if ($pid === 0) { $ch = curl_init($page); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $content = curl_exec($ch); curl_close($ch); if ($content) { file_put_contents($tmp_file, $content); exit(0); } else { exit(1); } } else if ($pid > 0) { pcntl_wait($status); $content = false; if (pcntl_wexitstatus($status) === 0) { $content = file_get_contents($tmp_file); } unlink($tmp_file); return $content; } else { unlink($tmp_file); return false; } }
Письмо на я могу сделать https-соединения в дочернем процессе.
fetch_page('https://www.google.ca/'); $pid = pcntl_fork(); if ($pid === 0) { $ch = curl_init('https://www.google.ca/'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $success = curl_exec($ch); var_dump($success !== false); // true } else if ($pid > 0) { // wait for child process pcntl_wait($status); } else { // handel fork error }