Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psysh appears to (c)lose mysqli connection #677

Closed
MonsieurCellophane opened this issue Jul 2, 2021 · 6 comments
Closed

psysh appears to (c)lose mysqli connection #677

MonsieurCellophane opened this issue Jul 2, 2021 · 6 comments

Comments

@MonsieurCellophane
Copy link

Greetings.
Using psysh v10.8 (great job BTW) to break in a moodle module I am developing. It appears that this causes the mysqli connection to go away in a semi-random fashion (meaning moving breaks around results in different outcomes).
The diagnostic is:

Couldn't fetch mysqli in [...]/lib/dml/mysqli_native_moodle_database.php

This error is always present at exit, but it does also appear during program execution depending on the breakpoint(s) location (and just before errors, $DB->mysqli->ping() returns indeed false).

I use ^D to get out of a breakpoint and continue execution, and I am speculating that the destructor for the global $DB object is called when i do that (the destructor calls mysqli->close()).

Is that what I am seeing, and if so, can it be avoided?

@MonsieurCellophane
Copy link
Author

MonsieurCellophane commented Jul 2, 2021

I put together a minimal CLI script illustrating the issue.
This (given correct credentials: replace username and password in the code) runs to the end if invoked as php cli.php while bombing on the second and third ->ping() (and ->close) if invoked as php cli.php -d. This with either mysqli.reconnect=Off or On in php.ini

<?php
$options=getopt("dv",["debug","verbose"],$rst_index);
$me=$argv[0];
if(is_array($options)) {
    $i=0;
    while($i<$rst_index){array_shift($argv);$i++;}
    $DBG=array_key_exists('d',$options) || array_key_exists('debug',$options);
    $VERBOSE=array_key_exists('v',$options) || array_key_exists('verbose',$options);
} else {
    error_log("Error in parsing CLI arguments:",join(',',$argv));
    die("Aborted\n");
}
if($DBG) {
    try {
        require('vendor/autoload.php');
    } catch (Exception $e) {
        error_log("In require: " . $e->getMessage() . "\n");
    }
}
$PSYSH=function_exists('psy\debug'); 
$conn=new mysqli('localhost','root','x'); // OK
$conn->ping();                            // OK
if ($PSYSH) { eval(\Psy\Sh()); }
$conn->ping();                            // FAILS with -d
if ($PSYSH) { eval(\Psy\Sh()); }
echo $conn->ping();                       //FAILS with -d
$conn->close();

@MonsieurCellophane
Copy link
Author

Also:

# php -v
PHP 7.3.27 (cli) (built: Feb  2 2021 10:32:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.27, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.27, Copyright (c) 1999-2018, by Zend Technologies

@bobthecow
Copy link
Owner

Try disabling forking ('usePcntl' => false in psysh config ).

@bobthecow
Copy link
Owner

Yep, confirmed with your repro script. It seems like mysqli doesn't play nice with forking. It's probably that one of the other threads automatically cleaned up the connection while the main thread wasn't looking?

I've also confirmed that disabling pcntl via the psysh config fixes your issue.

@MonsieurCellophane
Copy link
Author

That's it. I can make the same happen, with no psysh in the loop, by opening a connection, forking, using it in children processes and exiting. After the first child terminates, the connection becomes useless for evey other process in the group (parent or child). I get "Mysql has gone away", not "couldn't fetch mysqli" but I think the root cause is the same. Mysql documentation mentions terminating connections on client exit, which could be the cause. I searched to see if signals are involved and, if so, ways to trap them before mysql gets wind of them, but no luck.

@bobthecow
Copy link
Owner

Updated the Troubleshooting page of the wiki. I'm not sure what else we can do with it from our end, especially since the error happens after the shell exits? ¯_(ツ)_/¯

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

No branches or pull requests

2 participants