Как Node.js молча вылетает без какой-либо информации? - PullRequest
7 голосов
/ 19 сентября 2019

Приложение молча умирает, когда открывает много SFTP-соединений.Я использую всевозможные обработчики событий process, и срабатывает только один process.on('exit',...

Я использую пакет npm для SFTP ssh2-sftp-client, который использует пакет ssh2 внизу.

Вот минимальный воспроизводимый код

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')
})

Как видите, он не должен выходить из бесконечного цикла, пока не возникнет ошибка.И это на самом деле не для некоторых итераций, но в конечном итоге он ускользает (обычно после <10 итераций) </em>.И единственный журнал, который я вижу, это

SFTP client emitted END
Catched!. Exit code: 0

На стороне сервера SFTP у меня есть следующие ограничения в sshd_config файле

MaxSessions 1
MaxStartups 1

, который я использую:

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

Вкратце, вопрос:

КакУзел может аварийно завершить работу без каких-либо событий ошибок / стековых трасс и кода выхода 0 ?

Обновление # 1

В комментариях было рекомендовано сделатьосновной дамп процесса и анализ его.

Как сделать дамп ядра при коде выхода 0?

Если я сделаю дамп ядра, что мне там искать?

Обновление # 2

Создана проблема в хранилище https://github.com/theophilusx/ssh2-sftp-client/issues/168

1 Ответ

0 голосов
/ 25 сентября 2019

Эта специфическая проблема была вызвана тем, что на удаленном сервере было разорвано TCP-соединение, а библиотека SSH2 вызывала только событие «end» без события «error».Это было помечено как ошибка в ssh2 и указано в проблемах для этого модуля.

Тем временем в ssh2-sftp-client был добавлен обходной путь.По существу, дополнительный «конечный» слушатель был добавлен на этапе подключения, что приведет к отклонению обещания подключения при возникновении конечного события.Выпущена новая версия пакета (v4.2.0), которая включает это исправление.

Для справочной информации - одна из причин, по которой трудно получить согласованные результаты, когда отслеживание этой проблемы частично связано с настройкой MaxStartups многих SFTP-серверов (например, openSSH).Этот параметр может быть кортежем вида max: drop: full, где max - это максимально допустимые неаутентифицированные соединения (соединения, которые еще не завершили квитирование и процесс аутентификации), drop - процент соединений, которые начинают сбрасываться после того, как max достигнуто и заполнено= количество неаутентифицированных подключений, чтобы начать отбрасывать все попытки подключения.Значением по умолчанию часто является 10:30:60, что означает, что разрешено 10 соединений без аутентификации, начните отбрасывать 30% из них, если их больше 10, и отбрасывать все попытки, если произойдет 60 соединений без аутентификации.Значение сброса означает, что если существует более 10 неаутентифицированных соединений, попытки будут отбрасываться в 30% случаев, что создает несколько случайный результат: каждый раз, когда вы запускаете тесты, разные соединения могут быть сброшены.Серверы часто просто сбрасывают соединение, не предоставляя никакой дополнительной информации - вы можете или не можете получить сброс по ошибке однорангового узла, в зависимости от того, как сервер выполняет сброс (часто вы просто получаете конечное событие и ничего больше - ошибка не возникает),

...