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

Fix calling then on connecting that can be null #106

Closed
wants to merge 0 commits into from
Closed

Fix calling then on connecting that can be null #106

wants to merge 0 commits into from

Conversation

choval
Copy link

@choval choval commented May 8, 2019

After some idle time, the fist call gets:

Fatal error: Uncaught Error: Call to a member function then() on null in .../vendor/react/mysql/src/Io/LazyConnection.php:94

Due to connecting attribute being null, changed to connecting() method.

@clue
Copy link
Contributor

clue commented May 8, 2019

@choval Thanks for spotting and reporting!

Unfortunately, the PR does not contain any documentation or tests, so it's a bit unclear what you're trying to achieve from the snippet you've posted.

May I ask you provide a simple gist of what you're trying to achieve, i.e. how can this be reproduced and how can we be sure this issue is actually resolved and we do not introduce any regressions in the future? Thanks!

@choval
Copy link
Author

choval commented May 8, 2019

Having a hard time reproducing this.

What basically happens is the connection closes on the database side, the connection is nullified before the idleTimer is cancelled.

$connection->on('close', function () {
$this->connecting = null;
if ($this->idleTimer !== null) {
$this->loop->cancelTimer($this->idleTimer);
$this->idleTimer = null;
}
});

My script somehow managed to run the idleTimer before the cancelTimer, and after connecting = null (yay for async).

So, my proposal would actually trigger a new connection, which is totally wrong, since the whole purpose of the timer is to idle it... not reconnect it. (Made it in a hurry, since it breaks the server with a fatal error)

I'm thinking, maybe check if its null or canceling the timer before nullifying connecting?

nullifying connecting after canceling the timer

if ($this->idleTimer !== null) {
    $this->loop->cancelTimer($this->idleTimer);
    $this->idleTimer = null;
}
$this->connecting = null;

or just checking if its not null before expecting a promise on connecting

function idle()
{
  --$this->pending;

  if ($this->pending < 1 && $this->idlePeriod >= 0) {
    $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () {
      if($this->connecting !== null) {
        $this->connecting->then(function (ConnectionInterface $connection) {
          $this->disconnecting = $connection;
          $connection->quit()->then(
            function () {
              // successfully disconnected => remove reference
              $this->disconnecting = null;
            },
            function () use ($connection) {
              // soft-close failed => force-close connection
              $connection->close();
              $this->disconnecting = null;
            }
          );
        });
      }
      $this->connecting = null;
      $this->idleTimer = null;
    });
  }
}

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

Successfully merging this pull request may close these issues.

2 participants