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

sftp.put hangs after creating the file #247

Closed
p-j opened this issue Jul 21, 2020 · 17 comments
Closed

sftp.put hangs after creating the file #247

p-j opened this issue Jul 21, 2020 · 17 comments
Labels
external-dependency-bug Bug in external dependency of this module

Comments

@p-j
Copy link

p-j commented Jul 21, 2020

Hi,

I'm trying to do a simple upload of a small CSV file I'm generating on the fly.
Here is the relevant portion of the code

const data = Buffer.from(csv)
const sftp = new Client()
try {
  await sftp.connect({
    host: HOST,
    username: USERNAME,
    password: PASSWORD,
    port: PORT,
    debug: console.info
  })
  await sftp.put(data, '/path/to/file.csv')
} catch (e) {
  console.error(e)
} finally {
  await sftp.end()
}

When doing so, most of the time the upload will hang, with logs showing:

CLIENT[sftp]: exists -> /path/to/file.csv
CLIENT[sftp]: stat -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing STAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:60,padLen:9,remainLen:48
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: ATTRS
CLIENT[sftp]: stats <-  {
 "mode": 33206,
 "permissions": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "atime": 1595344292,
 "mtime": 1595347428
}
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
CLIENT[sftp]: exists <-  {
 "mode": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "accessTime": 1595344292000,
 "modifyTime": 1595347428000,
 "isDirectory": false,
 "isFile": true,
 "isBlockDevice": false,
 "isCharacterDevice": false,
 "isSymbolicLink": false,
 "isFIFO": false,
 "isSocket": false
}
CLIENT[sftp]: put remote path info  {
 "path": "/path/to/file.csv",
 "type": "-",
 "valid": true
}
CLIENT[sftp]: put -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing OPEN
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: put source is a buffer
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:17,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: HANDLE
DEBUG[SFTP]: Outgoing: Writing FSETSTAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG[SFTP]: Outgoing: Writing WRITE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 98482)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)

and it will stay like so forever

Sometime, completely at random, it will go through and in thise case the logs will be like that:

CLIENT[sftp]: exists -> /path/to/file.csv
CLIENT[sftp]: stat -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing STAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:60,padLen:9,remainLen:48
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: ATTRS
CLIENT[sftp]: stats <-  {
 "mode": 33206,
 "permissions": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "atime": 1595344292,
 "mtime": 1595347522
}
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
CLIENT[sftp]: exists <-  {
 "mode": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "accessTime": 1595344292000,
 "modifyTime": 1595347522000,
 "isDirectory": false,
 "isFile": true,
 "isBlockDevice": false,
 "isCharacterDevice": false,
 "isSymbolicLink": false,
 "isFIFO": false,
 "isSocket": false
}
CLIENT[sftp]: put remote path info  {
 "path": "/path/to/file.csv",
 "type": "-",
 "valid": true
}
CLIENT[sftp]: put -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing OPEN
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: put source is a buffer
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:17,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: HANDLE
DEBUG[SFTP]: Outgoing: Writing FSETSTAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG[SFTP]: Outgoing: Writing WRITE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 98482)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 102171)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG[SFTP]: Outgoing: Writing CLOSE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Outgoing: Writing DISCONNECT (BY_APPLICATION)
CLIENT[sftp]: Removing listener from error

I'm currently running Node v14.4.0, so I'm wondering if this could be linked to mscdex/ssh2-streams#156 ?

You mention in this issue that using a concurrency of 1 it's working all the time, and my understanding was that client.put is running in the same configuration which is why I'm opening this issue here as I'm not sure it's the same.

Do you have any idea what I could do to ensure a more consistent result while running Node >= v14.1.0 ?

Thanks

@theophilusx
Copy link
Owner

theophilusx commented Jul 21, 2020 via email

@p-j
Copy link
Author

p-j commented Jul 21, 2020

Thanks for your response @theophilusx
I plan on checking this by the end of the week. I'll be posting some feedback then.

@p-j
Copy link
Author

p-j commented Jul 23, 2020

Hi @theophilusx
I've tested both Node v13.14 and Node v14.5 today.
Both works fine with very small files.
Moving to larger files (in my case 842Ko CSV File)
Node v13.14 continues to produce good result but Node v14.5 hangs after creating the file. I end up with an empty file on the sftp server.

I'll be conducting more tests tomorrow with Node 14.0 & upward to see if the issue is indeed introduced by v14.1 as reported in the other issue.

@theophilusx
Copy link
Owner

theophilusx commented Jul 23, 2020 via email

@p-j
Copy link
Author

p-j commented Jul 27, 2020

I can confirm this is working on v14.0.0 and not on v14.1.0 with a big enough file.

@p-j
Copy link
Author

p-j commented Jul 27, 2020

I've also been able to reproduce the behavior with both

On Node >= 14.1 node buffer-test.js 1000 /home/test will hang most of the time
On Node <= 14.0 node buffer-test.js 1000 /home/test will go through most of the time

@theophilusx
Copy link
Owner

theophilusx commented Jul 27, 2020 via email

@theophilusx
Copy link
Owner

theophilusx commented Aug 4, 2020 via email

@theophilusx
Copy link
Owner

theophilusx commented Aug 4, 2020 via email

@p-j
Copy link
Author

p-j commented Aug 4, 2020

Hi @theophilusx
I've made a small change to your script here: master...p-j:master
This highlights the following, in v13.12.0 I get the following:

jeremie@xps ➜  tools git:(master) ✗ node lowlevel-buffer-put.js 1000 /home/test/$(date +"%Y-%m-%d_%H-%M-%S").bin
Uploading buffer of 1024000 bytes to /home/test/2020-08-04_09-46-02.bin
write stream pipe
read stream resume
read stream data
read stream pause
read stream end
File successfully uploaded to /home/test/2020-08-04_09-46-02.bin
write stream unpipe

while running v14.7.0

jeremie@xps ➜  tools git:(master) ✗ nvm use v14.7   
Now using node v14.7.0 (npm v6.14.7)
jeremie@xps ➜  tools git:(master) ✗ node lowlevel-buffer-put.js 1000 /home/test/$(date +"%Y-%m-%d_%H-%M-%S").bin
Uploading buffer of 1024000 bytes to /home/test/2020-08-04_09-46-38.bin
write stream pipe
read stream resume
read stream data
read stream pause
read stream end
read stream close
^C

The difference being the close event being emitted in the v14.7 and not in the v13.12

@theophilusx
Copy link
Owner

theophilusx commented Aug 4, 2020 via email

@theophilusx
Copy link
Owner

theophilusx commented Aug 5, 2020 via email

@p-j
Copy link
Author

p-j commented Aug 10, 2020

Seems the root cause could be here nodejs/node#32887 (comment)

@theophilusx theophilusx added the external-dependency-bug Bug in external dependency of this module label Aug 20, 2020
@theophilusx
Copy link
Owner

The ssh2 module is being re-written to address this and some other limitations of that module. The ssh2-streams module is also being deprecated. This means a re-write of ssh2-sftp-client will be necessary to work with the updated ssh2 module.

I have created the branch version-6, which will be used to do the re-write.

@p-j
Copy link
Author

p-j commented Oct 26, 2020

Thanks for the heads up, I might have some free time in the coming weeks if you want a hand in doing so I'd be happy to help.

@theophilusx
Copy link
Owner

Update: I have recently tested against the new ssh2 version. While the issues specific to fastPut and fastGet appear to be resolved in the new ssh2 version, there are still some issues with put/get which appear to be related to streams. The seems to still be a bit of work required on the new version of ssh2 before it will be ready for a release.

I have tested the existing 0.8.9 version of ssh2 against latest node v15.4.0. The changes introduced in node v14.x which caused problems with ssh2 have been rolled back. This means that ssh2 and ssh2-sftp-client seems to work OK with node version 15.4.0. However, the changes which were rolled back did provide significant performance improvements in other areas, so it is likely that at some point they will be re-applied in one fashion or another. Hopefully, the new version of ssh2 will be released before this occurs.

@theophilusx
Copy link
Owner

A new version of ssh2 has been released which addresses the underlying issue which caused this issue. I will be releasing ssh2-sftp-client 7.0.0 in a week. The new version works with all known versions of node >= v10.

I'm closing this issue as it has been resolved upstream with the new ssh2 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external-dependency-bug Bug in external dependency of this module
Projects
None yet
Development

No branches or pull requests

2 participants