amphp/postgres

Cannot set connection to nonblocking mode

vlakarados opened this issue · 4 comments

Stumbled upon this problem when trying out this library.
The connection is established, fully functional, query gets executed with no problem, after some time it seems I lose the connection:

[2018-06-08 12:09:38] server.debug: Accept ::1:58915 on ::1:1337 #151 [] []
[2018-06-08 12:09:38] server.debug: GET http://localhost:1337/ HTTP/1.1 @ ::1:58914 [] []
[2018-06-08 12:09:38] server.debug: GET http://localhost:1337/favicon.ico HTTP/1.1 @ ::1:58914 [] []
[2018-06-08 12:09:52] server.debug: Close ::1:58915 #151 [] []
[2018-06-08 12:09:53] server.debug: Close ::1:58914 #150 [] []
[2018-06-08 14:40:47] server.debug: Accept ::1:57156 on ::1:1337 #156 [] []
[2018-06-08 14:40:47] server.debug: Accept ::1:57157 on ::1:1337 #157 [] []
[2018-06-08 14:40:47] server.debug: GET http://localhost:1337/ HTTP/1.1 @ ::1:57156 [] []
PHP Notice:  pg_connection_busy(): Cannot set connection to nonblocking mode in /amp/vendor/amphp/postgres/lib/PgSqlHandle.php on line 107

Notice: pg_connection_busy(): Cannot set connection to nonblocking mode in /amp/vendor/amphp/postgres/lib/PgSqlHandle.php on line 107
[2018-06-08 14:40:47] server.error: Amp\Postgres\QueryExecutionError: socket not open  in /amp/vendor/amphp/postgres/lib/PgSqlHandle.php:320 Stack trace: #0 [internal function]: Amp\Postgres\PgSqlHandle->Amp\Postgres\{closure}() #1 /amp/vendor/amphp/amp/lib/Coroutine.php(74): Generator->send(Resource id #158) #2 /amp/vendor/amphp/amp/lib/Internal/Placeholder.php(127): Amp\Coroutine->Amp\{closure}(NULL, Resource id #158) #3 /amp/vendor/amphp/amp/lib/Deferred.php(41): class@anonymous->resolve(Resource id #158) #4 /amp/vendor/amphp/postgres/lib/PgSqlHandle.php(111): Amp\Deferred->resolve(Resource id #158) #5 /amp/vendor/amphp/amp/lib/Loop/NativeDriver.php(172): Amp\Postgres\PgSqlHandle::Amp\Postgres\{closure}('o', Resource id #125, NULL) #6 /amp/vendor/amphp/amp/lib/Loop/NativeDriver.php(68): Amp\Loop\NativeDriver->selectStreams(Array, Array, 0.94) #7 /amp/vendor/amphp/amp/lib/Loop/Driver.php(130): Amp\Loop\NativeDriver->dispatch(true) #8 /amp/vendor/amphp/amp/lib/Loop/Driver.php(70): Amp\Loop\Driver->tick() #9 /amp/vendor/amphp/amp/lib/Loop.php(76): Amp\Loop\Driver->run() #10 /amp/run.php(111): Amp\Loop::run(Object(Closure)) #11 {main} [] []
[2018-06-08 14:40:47] server.debug: GET http://localhost:1337/favicon.ico HTTP/1.1 @ ::1:57156 [] []
[2018-06-08 14:41:02] server.debug: Close ::1:57156 #156 [] []
[2018-06-08 14:41:02] server.debug: Close ::1:57157 #157 [] []

as you may see @ 12:09:38 this runs with no problem, the query gets executed, result returned, after being idle, at 14:40:47 (actually this happened to me with ±5minutes in idle as well) there's this error happening.

Should I be "pinging" the database every minute or so to keep the connection alive, or should I reestablish it after some time?

Here's the code (but it actually is a bunch of amp examples clumped together)

Amp\Loop::run(function () {
    $sockets = [
        Socket\listen("0.0.0.0:1337"),
        Socket\listen("[::]:1337"),
    ];

    $logHandler = new StreamHandler(new ResourceOutputStream(\STDOUT));
    $logHandler->setFormatter(new ConsoleFormatter);
    $logger = new Logger('server');
    $logger->pushHandler($logHandler);


    /** @var \Amp\Postgres\Pool $pool */
    $pool = Amp\Postgres\pool("host=xxx user=xxx dbname=xxx password=xxx");

    $router = new Router;

    $router->addRoute('GET', '/', new CallableRequestHandler(function () use ($pool) {
        $statement = yield $pool->prepare("SELECT * FROM users ORDER BY user_id ASC LIMIT 100");

        /** @var \Amp\Postgres\ResultSet $result */
        $result = yield $statement->execute();

        return new Response(Status::OK, [
            "content-type" => "text/plain; charset=utf-8",
        ], new IteratorStream(new Producer(function (callable $emit) use ($result) {
            while (yield $result->advance()) {
                $row = $result->getCurrent();

                yield $emit($row['user_id'].': '.$row['email']."\r\n");
            }
        })));
    }));

Looks like you're using 0.2.x, try with master as pools now automatically close idle connections. The BC breaks are minor, so you should be able to update without changes to your code.

Please upgrade to v1.0.0 and reopen this issue if you have any further problems.

I'm really sorry for not posting back, master branch did help, v1.0.0 will be tested later

PNixx commented

I see a same error on v1.3.3. I set a pool 10 connection and receive error after 1-2 minutes:

pg_connection_busy(): Cannot set connection to nonblocking mode, /project/vendor/amphp/postgres/src/PgSqlHandle.php:109

When I used pool 5, I did not observe such a problem.