sanketbajoria / ssh2-promise

ssh with promise/async await and typescript support
https://www.npmjs.com/package/ssh2-promise
MIT License
148 stars 25 forks source link

createReadStream does not finish when connection is killed #27

Closed jeffrson closed 5 years ago

jeffrson commented 5 years ago

Hi, let's say I have this program to read an sftp stream via pure ssh2-streams:

const Client = require('ssh2').Client;

let srcSshConfig = {
    host: 'server',
    port: 22,
    username: 'user',
    password: 'pass'
}

let srcConn = new Client();
srcConn.connect(srcSshConfig)
srcConn.on('ready', () => {
    srcConn.sftp((err, sftpr) => {
        let count = 0
        let streamInput = sftpr.createReadStream('srcFile')
        streamInput.on('data', (chunk) => console.log(count++))
    })
})
srcConn.on('error', (err) => console.log('error!'))

When the server kills the connection (or the server is killed), I get "error!". This is expected.

OTOH, a similar program with SSH2Promise hangs forever when the connection will be killed:

const SSH2Promise = require('ssh2-promise')

let srcSshConfig = {
    host: 'server',
    port: 22,
    username: 'user',
    password: 'pass'
}

let srcSftp = new SSH2Promise(srcSshConfig).sftp()
srcSftp.on('error', (err) => console.log('error1'))
srcSftp.ssh.on('error', (err) => console.log('error2'))
srcSftp.createReadStream(srcFile).then(streamInput =>
            new Promise(async (resolve, reject) => {
                try {
                    let count=0
                    streamInput.on('error', (err) => { console.log('error3'); reject(err) })
                    streamInput.on('data', (chunk) => console.log(count++))
                } catch (err) {
                    console.log('error4')
                    reject(err)
                }
            }),
    )
    .catch(err => console.log('error5'))

I tried different on('error') handlers but it doesn't help. Well, btw, when I add "reconnect: false" option, the program simply exits - apparently because the event loop finishs. But without any message?!

I first thought this is a ssh2-streams bug, because ssh2-promise on the first sight only wraps createReadStream - but with pure ssh2-streams the program does not hang. Reference: https://github.com/mscdex/ssh2-streams/issues/127

Would be VERY grateful to get this solved.

jeffrson commented 5 years ago

Well, as it looks, the stream's 'error' event is hidden inside SSH2, which is swallowed inside your sshConnection:264-268. So I have no way to resolve or reject my promises :-(

Can there be a fix?

sanketbajoria commented 5 years ago

@jeffrson Actually, once promise get resolved, we won't be able to resolve/reject it again. That's why we are emitting the error. this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.DISCONNECT, {err: err}); Please, listen for SSH event and check for disconnect status

sanketbajoria commented 5 years ago

@jeffrson Should i close this issue? Has it got resolved for you

sanketbajoria commented 5 years ago

I am closing this issue for now. Please feel free to reopen this issue, if things didn't work out for you

jeffrson commented 5 years ago

Sorry for the lack of response - I've been too busy.

Yes, by listening for ssh disconnect I can resolve the issue - not nice, but it works.