swoole / swoole-src

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

Parent coroutine context gets lost when using coroutine hooks #4785

Closed zigapompe closed 2 years ago

zigapompe commented 2 years ago

When using coroutine hooks the parent coroutines in the upper chain are lost and you cannot access them. Coroutine::exists() with parent CIDs return false. You can test it yourself by disabling hooks in the code below and you will see the context data in the var_dump.

Please answer these questions before submitting your issue.

  1. What did you do? If possible, provide a simple script for reproducing the error.

    Runtime::enableCoroutine(SWOOLE_HOOK_ALL); // Parent context gets lost if coroutine hook is enabled

    go(function () {
    
        // Set a variable in coroutine context
        Coroutine::getContext()['test_var'] = 123;
    
        go(function () {
    
           // Run curl in coroutine
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => 'http://127.0.0.1/',
                CURLOPT_RETURNTRANSFER => 1,
            ]);
    
            curl_exec($curl);
    
            var_dump([
                'CID' => Coroutine::getCid(),
                'PCID' => Coroutine::getPcid(),
                'Parent context' => Coroutine::getContext(Coroutine::getPcid()),
                'Parent exists' => Coroutine::exists(Coroutine::getPcid()),
            ]);
    
        });
    
    });
  2. What did you expect to see?

array(4) { ["CID"]=> int(2) ["PCID"]=> int(1) ["Parent context"]=> object(Swoole\Coroutine\Context)#1129 (1) { ["storage":"ArrayObject":private]=> array(1) { ["test_var"]=> int(123) } } ["Parent exists"]=> bool(true) }

  1. What did you see instead?

array(4) { ["CID"]=> int(2) ["PCID"]=> int(1) ["Parent context"]=> NULL ["Parent exists"]=> bool(false) }

  1. What version of Swoole are you using (show your php --ri swoole)?

php --ri openswoole

openswoole

Open Swoole => enabled Author => Open Swoole Group hello@openswoole.com Version => 4.11.1 Built => Jun 20 2022 12:30:22 coroutine => enabled with boost asm context epoll => enabled eventfd => enabled signalfd => enabled cpu_affinity => enabled spinlock => enabled rwlock => enabled sockets => enabled openssl => OpenSSL 1.1.1f 31 Mar 2020 dtls => enabled http2 => enabled json => enabled curl-native => enabled pcre => enabled zlib => 1.2.11 mutex_timedlock => enabled pthread_barrier => enabled futex => enabled mysqlnd => enabled async_redis => enabled

Directive => Local Value => Master Value swoole.enable_coroutine => On => On swoole.enable_library => On => On swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => On => On swoole.unixsock_buffer_size => 8388608 => 8388608

  1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?

uname -a Linux homestead 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

php -v PHP 8.1.7 (cli) (built: Jun 25 2022 08:12:59) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.7, Copyright (c) Zend Technologies with Zend OPcache v8.1.7, Copyright (c), by Zend Technologies

gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:hsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)

NathanFreeman commented 2 years ago
<?php
use Swoole\Runtime;
use Swoole\Coroutine;
use Swoole\Coroutine\WaitGroup;

Runtime::enableCoroutine(SWOOLE_HOOK_ALL); // Parent context gets lost if coroutine hook is enabled

$waitGroup = new WaitGroup();

go(function () use ($waitGroup){

    // Set a variable in coroutine context
    Coroutine::getContext()['test_var'] = 123;

    go(function () use ($waitGroup){
        $waitGroup->add();
        // Run curl in coroutine
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => 'http://127.0.0.1/',
            CURLOPT_RETURNTRANSFER => 1,
        ]);

        curl_exec($curl);

        var_dump([
            'CID' => Coroutine::getCid(),
            'PCID' => Coroutine::getPcid(),
            'Parent context' => Coroutine::getContext(Coroutine::getPcid()),
            'Parent exists' => Coroutine::exists(Coroutine::getPcid()),
        ]);
        $waitGroup->done();
    });
    $waitGroup->wait();
});
NathanFreeman commented 2 years ago

There is no relationship between parent and child coroutine. They are independent programs. You can use Swoole\Coroutine\WaitGroup to let the parent coroutine wait for the child coroutine.

leocavalcante commented 2 years ago

Try swoole instead of openswoole 😜

image

zigapompe commented 2 years ago

It works, thanks guys :)