swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.44k stars 3.16k forks source link

co http client segmentation fault #2192

Closed limingxinleo closed 5 years ago

limingxinleo commented 5 years ago
<?php

use Swoole\Coroutine\Http\Client;

go(function () {
    $client = new Client('echo.swoft.org', 80);
    $client->setMethod('GET');
    $client->setHeaders([
        'Host' => "localhost",
        "User-Agent" => 'Chrome/49.0.2587.3',
        'Accept' => 'text/html,application/xhtml+xml,application/xml',
        'Accept-Encoding' => 'gzip',
    ]);
    $client->set([
        'timeout' => 2
    ]);
    $client->execute('/');
    var_dump($client->body);
    $client->close();
});

\Swoole\Event::wait();

go(function () {
    $client = new Client('echo.swoft.org', 80);
    $client->setMethod('GET');
    $client->setHeaders([
        'Host' => "localhost",
        "User-Agent" => 'Chrome/49.0.2587.3',
        'Accept' => 'text/html,application/xhtml+xml,application/xml',
        'Accept-Encoding' => 'gzip',
    ]);
    $client->set([
        'timeout' => 2
    ]);
    $client->execute('/');
    var_dump($client->body);
    $client->close();
});

\Swoole\Event::wait();

当我使用协程时,中间使用\Swoole\Event::wait();等待回收协程,当再次执行后,会抛出这个错误

$ php test.php
string(379) "{"headers":{"Host":"localhost","X-Real-Ip":"103.108.2.22","X-Forwarded-For":"103.108.2.22","Connection":"close","User-Agent":"Chrome\/49.0.2587.3","Accept":"text\/html,application\/xhtml+xml,application\/xml","Accept-Encoding":"gzip"},"server":[],"method":"GET","uri":{"scheme":"http","userInfo":"","host":"localhost","port":80,"path":"\/","query":"","fragment":""},"body":false}"
[1]    18650 segmentation fault  php test.php
limingxinleo commented 5 years ago
<?php
$id = go(function () {
    echo 1;
    \co::sleep(1);
    echo 2;
});

\Swoole\Event::wait();

go(function () {
    echo 1;
    \co::sleep(1);
    echo 2;
});

这样就可以复现,最后一个echo 2打不出来

matyhtf commented 5 years ago

请在程序末尾添加 Swoole\Event::wait(),勿调用两次。

limingxinleo commented 5 years ago

那我有什么办法,可以等待协程回收么?我在写单元测试,不希望我单测内的协程交叉执行

matyhtf commented 5 years ago

可以用 swoole_event_dispatch,你可以换个思路去实现。

twose commented 5 years ago
 go(function () {
    global $argc, $argv;
    require '/path/to/phpunit.phar';
});