How Node.js silently crashes without any information?

LEQ*_*ADA 7 javascript sftp asynchronous node.js ssh-tunnel

Application silently dies when it opens a lot of SFTP connections. I use all sorts of process event handlers and the only one triggered is process.on('exit',...

I'm using an npm package for SFTP ssh2-sftp-client which is using ssh2 package underneath.

Here is a minimal reproducible code

const Client = require('ssh2-sftp-client')
const inspect = require('util').inspect

const sftpClient = new Client();

sftpClient.on('error', (err) => {
  console.log('SFTP client emitted ERROR: ' + inspect(err))
})
sftpClient.on('end', () => {
  console.log('SFTP client emitted END')
})
sftpClient.on('finish', () => {
  console.log('SFTP client emitted FINISH')
})
sftpClient.on('close', () => {
  console.log('SFTP client emitted CLOSE')
})

const options = {
  host: '',
  port: '22',
  username: '',
  password: ''
};

// below infinite loop is to simulate large number of 
// connections in my production code
(async () => {
  while (true) {
    try {
      await new Promise(resolve => setTimeout(() => resolve(sftpClient.connect(options)), 1000))
    } catch {
      console.log('boom')
    }
  }
})()

process.on('exit', code => console.log(`Catched!. Exit code: ${code}`))

process.on('uncaughtException', (err, origin) => {
  console.error('Unhandled exception. Please handle!', err.stack || err)
  console.error(`Origin: ${JSON.stringify(origin)}`)
})

process.on('unhandledRejection', (err, promise) => {
  console.error('Unhandled promise rejection. Please handle!', promise, err.stack || err)
})

process.on('warning', (warning) => {
  console.warn(warning.name)
  console.warn(warning.message)
  console.warn(warning.stack)
})

process.on('rejectionHandled', (promise) => {
  console.log('rejectionHandled event triggered')
})

Run Code Online (Sandbox Code Playgroud)

As you can see, it shouldn't escape the infinite loop unless there is an Error. And it in fact does not for some iterations but eventually it escapes (usually after <10 iterations). And the only log I see is

SFTP client emitted END
Catched!. Exit code: 0
Run Code Online (Sandbox Code Playgroud)

On the SFTP server side I have the following limitations in the sshd_config file

MaxSessions 1
MaxStartups 1
Run Code Online (Sandbox Code Playgroud)

I'm using:

  • Node.js 12
  • ssh2-sftp-client 4.1.0

In brief, question:

How Node can crash without any error events/stacktraces and exit code 0?

Update #1

It was recommended in the comments to make a core dump of the process and analyse it.

How can I make a core dump on exit code 0?

如果要进行核心转储,我应该在那里找什么?

更新#2

在存储库https://github.com/theophilusx/ssh2-sftp-client/issues/168中创建了一个问题

Tim*_*m X 2

此特定问题是由远程服务器断开 TCP 连接和 SSH2 库仅引发“结束”事件而没有“错误”事件的组合引起的。这已被标记为 ssh2 中的错误,并列在该模块的问题中。

同时,ssh2-sftp-client 中添加了解决方法。本质上,在连接阶段添加了一个额外的“结束”侦听器,如果引发结束事件,这将导致连接承诺被拒绝。该软件包的新版本 (v4.2.0) 已发布,其中包含此修复程序。

背景信息 - 追踪此问题时难以获得一致结果的部分原因是许多 SFTP 服务器(如 openSSH)的 MaxStartups 设置。此设置可以是 max:drop:full 形式的元组,其中 max 是允许的最大未经身份验证连接(尚未完成握手和身份验证过程的连接),drop - 达到 max 并已满后开始丢弃的连接百分比= 开始丢弃所有连接尝试的未经身份验证的连接数。默认值通常为 10:30:60,这意味着允许 10 个未经身份验证的连接,一旦超过 10 个,则开始丢弃其中的 30%,一旦出现 60 个未经身份验证的连接,则丢弃所有尝试。drop 值意味着一旦存在超过 10 个未经身份验证的连接,30% 的时间尝试将被丢弃,这会产生一个有点随机的结果,即每次运行测试时,可能会丢弃不同的连接。服务器通常会直接断开连接,而不提供任何附加信息 - 您可能会或可能不会因对等错误而重置,具体取决于服务器如何执行断开操作(通常,您只会收到结束事件,仅此而已 - 不会引发错误) 。