Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Segmentation fault when run in distinct coroutine context #55

Open
sergiotabanelli opened this issue Apr 30, 2021 · 3 comments
Open

Segmentation fault when run in distinct coroutine context #55

sergiotabanelli opened this issue Apr 30, 2021 · 3 comments

Comments

@sergiotabanelli
Copy link

sergiotabanelli commented Apr 30, 2021

The following code produce a segmentation fault. The problem is that the registration of coroutine callbacks were done only in the connect method. I have a fork that fix this bug. I can do a pull request if needed.

<?php
$db;
\Co\run(function() use (&$db){
    $db = new \Swoole\Coroutine\PostgreSQL();
    $db->connect("host=127.0.0.1 port=5432 dbname=wireskel user=wireskel password=xxxxxx");
});
\Co\run(function () use ($db) {
    $res = $db->query('SELECT * from _cred_user'); // Segmentation Fault
});
@sergiotabanelli
Copy link
Author

sergiotabanelli commented May 10, 2021

Hi, may I have a feedback? I have created a pull request that fix the bug. I think that run this extension in distinct coroutine contexts can be useful in unit testing and other things!

@codercms
Copy link
Collaborator

@sergiotabanelli hi! I think you shouldn't use Coroutine objects in this manner.

Coroutine::run - creates one global app event loop, application may have only one event loop at once.
You trying to create two event loops in sequence. $db object belongs to your first event loop, but you trying to access $db from different event loop. But this case should never happen (for example: because Postgres socket is bound to the first event loop).

Your app arch should be like:

php main.php

// main.php content
<?php

// create event loop
\Co\run(function() {
    // you're inside event loop now

    $db = new \Swoole\Coroutine\PostgreSQL();
    $db->connect("host=127.0.0.1 port=5432 dbname=wireskel user=wireskel password=xxxxxx");

    \Swoole\Coroutine::create(function () use ($db) {
          $res = $db->query('SELECT * from _cred_user');
    });

    // Wait here for some events: e.g. coroutine exit or termination signal

    // disconnect from Postgres while you're in event loop
    unset($db);
});

exit(0);

@sergiotabanelli
Copy link
Author

@codercms thanks for Your answer, but I have to disagree.
IMHO:

  • The same scenario perfectly works with pdo_mysql and mysqli
  • This is a segmentation fault! so, at least the main swoole extension should consider this as a security bug. Indeed the swoole extension should at least check if the event callback is a valid pointer.
  • In my understanding of the swoole source code, the postgres socket, can't be "bound to the first event loop" because otherwise the scheduler does not exit from the event loop and the second event loop can't be initialized.
  • As an example... this pattern is usefull for phpunit and cronjobs or batchs .... in our tests we init a connection in setUp() or in setUpBeforeClass(), use the connection in tests and unset it in tearDown() or tearDownAfterClass().
  • What do You mean with "application may have only one event loop at once"? My reported example does not have multiple event loops running at same time!
  • And also ... for phpunit tests where would You put the \Co\run? If You put it in test methods You end up with multiple \Co\run executed in the same php cli process as with my example! Same question for a php cronjob manager.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants