Node js Дочерний канал процесса закрывается с ошибкой [ERR_IPC_CHANNEL_CLOSED] при запуске Visual Studio Code Inspector - PullRequest
0 голосов
/ 23 марта 2020

Я работаю над приложением koa с командой разработчиков, использующих код Visual Studio. В последние две недели мы видели эту ошибку, когда отправляли сообщение в Node.js дочерний процесс

Error [ERR_IPC_CHANNEL_CLOSED]: Channel closed at ChildProcess.target.send (internal/child_process.js:678:16)

Мы запускаем приложение в нашем пакете json примерно так :

"nodemon --exec 'node --inspect=7003 index.js'"

Когда я удаляю оператор --inspect=7003, дочерний процесс работает должным образом. Когда я запускаю его с инспектором, я получаю эти ошибки вместе с дочерним процессом, закрывающим канал, как только сообщение отправляется

Starting inspector on 127.0.0.1:7003 failed: address already in use

Я получаю эти ошибки независимо от того, какой порт I попробуйте запустить инспектора.

У меня есть коллега, который запускает код в Windows ОС, тогда как я использую MacOS и не получаю ни одной из ошибок, мы оба запускаем код с node -v 12.6.0 и vscode 1.43.1. У нас есть другой коллега, у которого ошибка канала закрыта, независимо от того, работает ли он инспектором или нет.

У нас также есть приложение, работающее в облаке, и мы периодически получаем ту же ошибку, даже если у нас не работает инспектор.

Я проверил, и нормальное поведение приложения успешно закрывает дочерние процессы, и у меня нет возможности проверить, не нарушают ли некоторые из них некоторые дочерние процессы, открытые и потерянные.

Я создал простое приложение, в котором я могу повторить проблему локально, вот код:

Индекс. js

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const helmet = require('koa-helmet');
const routes = require('./routes');

const PORT = 3088;

const app = new Koa();

app.use(helmet());

app.use(bodyParser());

app.use((ctx, next) => {
  const key = ctx.get('health');

  if (key) {
    return (ctx.response.status = 200);
  }
  return next();
});

routes(app);

app.listen(PORT, () => {
  console.log(`App running on port: ${PORT}`);
});

маршруты. js

const { processThing } = require('./parent.js');
const Router = require('koa-router');

const router = new Router();

router.get('/process', processThing);

module.exports = app => {
    app.use(router.routes());
  };

parent. js


const { fork } = require('child_process');

const forked = fork(`${__dirname}/child-process.js`);

const processThing = async ({ request, response }) => {
    console.log('doing processing')

    // we do something asynchronous in our actual code base

  const TIMEOUT = 1800000;

  forked.on('message', async ({ status, error }) => {
    timeoutId && clearTimeout(timeoutId);
    forked.kill();
    console.log('status', status)
      return status;
    })

  forked.on('error', async error => {
      console.log(error, 'error')
    timeoutId && clearTimeout(timeoutId);
    forked.kill();
  });

  console.log('sending hello')

  forked.send('hello');

  timeoutId = setTimeout(async () => {
    forked.kill();
    console.log('timed out')}, TIMEOUT);

 // send message to say that child process has started processing
  response.status = 204;
  return response;
};

module.exports = { processThing };

child-process. js

process.on('message', async string => {
    console.log('did thing');
    process.send({
      status: 'DONE'
    });
  });

package. json

{
  "name": "test-child-process",
  "version": "1.0.0",
  "description": "",
  "main": "child-process.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon --exec 'node --inspect=7003 index.js'"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "koa": "^2.11.0",
    "koa-bodyparser": "^4.2.1",
    "koa-helmet": "^5.2.0",
    "koa-router": "^8.0.8",
    "nodemon": "^2.0.2"
  }
}

Может кто-нибудь сказать мне, почему мы с коллегами закрыли этот канал по ошибке? Если это из-за потерянных дочерних процессов, есть ли у кого-нибудь предложения о том, как я могу их найти и убить?

---------------------- ПРАВКА ---------------------------------

С некоторой помощью мы поняли, что проблема была раздвоена вызов должен быть внутри метода, в противном случае при первоначальной сборке приложения создается только один дочерний процесс, и в конце концов он блокируется по тайм-ауту и ​​закрывается. Генерируя дочерний процесс внутри родительского метода, а также перезаписывая унаследованные аргументы (инспектор), он работает каждый раз:

Обновленный родительский. js

const { fork } = require('child_process');

const processThing = async ({ request, response }) => {
    console.log('doing processing')

    //this is now inside the function
    const forked = fork(`${__dirname}/child-process.js`, {
      execArgv: ['--max-old-space-size=6144']
    });

    // we do something asynchronous in our actual code base

  const TIMEOUT = 1800000;

  forked.on('message', async ({ status, error }) => {
    timeoutId && clearTimeout(timeoutId);
    forked.kill();
    console.log('status', status)
      return status;
    })

  forked.on('error', async error => {
      console.log(error, 'error')
    timeoutId && clearTimeout(timeoutId);
    forked.kill();
  });

  console.log('sending hello')

  forked.send('hello');

  timeoutId = setTimeout(async () => {
    forked.kill();
    console.log('timed out')}, TIMEOUT);

 // send message to say that child process has started processing
  response.status = 204;
  return response;
};

module.exports = { processThing };

Однако, когда я не перезаписывайте унаследованный аргумент инспектора, теперь он все еще не запускает дочерний процесс, но теперь не возвращает дочерние журналы консоли, он просто выходит из системы, что адрес уже используется. Я предполагаю, что инспектор, который не запускается, приводит к сбою дочернего процесса, и нам нужно посмотреть на совместное использование порта с ребенком, изменив запуск. json но если у кого-то есть какие-либо другие мысли или объяснения, я бы хотел их услышать.

...