11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci// Before https://github.com/nodejs/node/pull/2847 a child process trying
51cb0ef41Sopenharmony_ci// (asynchronously) to use the closed channel to it's creator caused a segfault.
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst cluster = require('cluster');
91cb0ef41Sopenharmony_ciconst net = require('net');
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciif (!cluster.isPrimary) {
121cb0ef41Sopenharmony_ci  // Exit on first received handle to leave the queue non-empty in primary
131cb0ef41Sopenharmony_ci  process.on('message', function() {
141cb0ef41Sopenharmony_ci    process.exit(1);
151cb0ef41Sopenharmony_ci  });
161cb0ef41Sopenharmony_ci  return;
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst server = net
201cb0ef41Sopenharmony_ci  .createServer(function(s) {
211cb0ef41Sopenharmony_ci    if (common.isWindows) {
221cb0ef41Sopenharmony_ci      s.on('error', function(err) {
231cb0ef41Sopenharmony_ci        // Prevent possible ECONNRESET errors from popping up
241cb0ef41Sopenharmony_ci        if (err.code !== 'ECONNRESET') throw err;
251cb0ef41Sopenharmony_ci      });
261cb0ef41Sopenharmony_ci    }
271cb0ef41Sopenharmony_ci    setTimeout(function() {
281cb0ef41Sopenharmony_ci      s.destroy();
291cb0ef41Sopenharmony_ci    }, 100);
301cb0ef41Sopenharmony_ci  })
311cb0ef41Sopenharmony_ci  .listen(0, function() {
321cb0ef41Sopenharmony_ci    const worker = cluster.fork();
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci    worker.on('error', function(err) {
351cb0ef41Sopenharmony_ci      if (
361cb0ef41Sopenharmony_ci        err.code !== 'ECONNRESET' &&
371cb0ef41Sopenharmony_ci        err.code !== 'ECONNREFUSED' &&
381cb0ef41Sopenharmony_ci        err.code !== 'EMFILE'
391cb0ef41Sopenharmony_ci      ) {
401cb0ef41Sopenharmony_ci        throw err;
411cb0ef41Sopenharmony_ci      }
421cb0ef41Sopenharmony_ci    });
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci    function send(callback) {
451cb0ef41Sopenharmony_ci      const s = net.connect(server.address().port, function() {
461cb0ef41Sopenharmony_ci        worker.send({}, s, callback);
471cb0ef41Sopenharmony_ci      });
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci      // https://github.com/nodejs/node/issues/3635#issuecomment-157714683
501cb0ef41Sopenharmony_ci      // ECONNREFUSED or ECONNRESET errors can happen if this connection is
511cb0ef41Sopenharmony_ci      // still establishing while the server has already closed.
521cb0ef41Sopenharmony_ci      // EMFILE can happen if the worker __and__ the server had already closed.
531cb0ef41Sopenharmony_ci      s.on('error', function(err) {
541cb0ef41Sopenharmony_ci        if (
551cb0ef41Sopenharmony_ci          err.code !== 'ECONNRESET' &&
561cb0ef41Sopenharmony_ci          err.code !== 'ECONNREFUSED' &&
571cb0ef41Sopenharmony_ci          err.code !== 'EMFILE'
581cb0ef41Sopenharmony_ci        ) {
591cb0ef41Sopenharmony_ci          throw err;
601cb0ef41Sopenharmony_ci        }
611cb0ef41Sopenharmony_ci      });
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    worker.process.once(
651cb0ef41Sopenharmony_ci      'close',
661cb0ef41Sopenharmony_ci      common.mustCall(function() {
671cb0ef41Sopenharmony_ci        // Otherwise the crash on `channel.fd` access may happen
681cb0ef41Sopenharmony_ci        assert.strictEqual(worker.process.channel, null);
691cb0ef41Sopenharmony_ci        server.close();
701cb0ef41Sopenharmony_ci      })
711cb0ef41Sopenharmony_ci    );
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci    worker.on('online', function() {
741cb0ef41Sopenharmony_ci      send(function(err) {
751cb0ef41Sopenharmony_ci        assert.ifError(err);
761cb0ef41Sopenharmony_ci        send(function(err) {
771cb0ef41Sopenharmony_ci          // Ignore errors when sending the second handle because the worker
781cb0ef41Sopenharmony_ci          // may already have exited.
791cb0ef41Sopenharmony_ci          if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED' &&
801cb0ef41Sopenharmony_ci                     err.code !== 'ECONNRESET' &&
811cb0ef41Sopenharmony_ci                     err.code !== 'ECONNREFUSED' &&
821cb0ef41Sopenharmony_ci                     err.code !== 'EMFILE') {
831cb0ef41Sopenharmony_ci            throw err;
841cb0ef41Sopenharmony_ci          }
851cb0ef41Sopenharmony_ci        });
861cb0ef41Sopenharmony_ci      });
871cb0ef41Sopenharmony_ci    });
881cb0ef41Sopenharmony_ci  });
89