I'm not really sure where to file this issue, but this is the package we're using, so I start here.
What is wrong?
When I use this SftpAdapter with the Laravel Storage facade in a Job, things blow up after a day or so.
The worker process starts, connects to the sFTP-server, and pushes files to it. At night, there is no work, so the connection times out. The first files in the morning are then failing with a Connection closed prematurely
. Since it's a Job in a worker-process, the Job fails, but the connection stays 'open' in the process. The only thing that helps is to restart the worker.
Debugging the problem
Before trying to upload, the SftpAdapter calls ->getConnection()
, which in turn calls ->isConnected()
, which has the following logic:
public function isConnected()
{
if ($this->connection instanceof SFTP && $this->connection->isConnected()) {
return true;
}
return false;
}
... where SFTP
is \phpseclib\Net\SFTP
, which inherits ->isConnected()
from \phpseclib\Net\SSH2
.
It looks like this:
/**
* Is the connection still active?
*
* @return bool
* @access public
*/
function isConnected()
{
return (bool) ($this->bitmap & self::MASK_CONNECTED);
}
And when I log it, it actually returns true
, right before the Connection closed prematurely
. The text in the docblock seems to tell us this is the right function to call, but the docblock on ->bitmap
tells a different story:
/**
* Execution Bitmap
*
* The bits that are set represent functions that have been called already. This is used to determine
* if a requisite function has been successfully executed. If not, an error should be thrown.
*
* @var int
* @access private
*/
var $bitmap = 0;
It seems to me that indeed, the ->connect()
function has already been called, but the connection has gone away, so we are not connected anymore.
There is a closed issue on phpseclib which suggest we should send a ping
to the host every so often, so we don't lose the connection.
Fix it here, then?
I don't think doing a ping is the right answer, but I think a solution could be to improve the SftpAdapter to have a better check for this connection.
Maybe it should detect / catch this Connection closed prematurely
Exception and call ->disconnect()
, setting it's ->connection
to null
? That could work.
Or do you think that this is in fact an issue in phpseclib, and I should open it there?