Skip to content

'close' event called before 'end' in paused stream #19166

@DiegoTUI

Description

@DiegoTUI

I believe I've found an akward behaviour of a stream in paused mode using the net module. In some specific cases, when the source socket ends, the close event is called before the end event in the destination socket. I've been able to reproduce it simulating the callback queue with nested setImmediates.

Server

'use strict';
                               
const net = require('net');    

let n=0;                       

const opts = {                 
  host: '127.0.0.1',
  port: 1100
};
  
const server = net.createServer(s => {
  let id = n++;                
  s.setEncoding('utf8');       
  s.on('readable', () => {
    setImmediate(() => 
      setImmediate(() => 
        setImmediate(() =>
          setImmediate(() => s.read()))));
  });
  s.on('end', () => console.trace(`Socket ${id} END`));
  s.on('close', () => console.trace(`Socket ${id} CLOSE`));
});

server.listen(opts, console.info.bind(null, 'server listening', opts));

I've tried with two clients.

Client 1 (bash)
$ echo EVENT | nc localhost 1100

Client 2 (node)

'use strict';

const net = require('net');

let n=0;

function runOnce() { 
  const s = net.connect(1100, () => { 
    console.info('Connected', n++);
    s.write('EVENT', () => { 
      s.end();
    });
  });
  return new Promise(ok => { 
    s.on('close', ok)
  })
}

async function run(times) {
  for (let i=0; i<times; i++) { 
    await runOnce();
  }
}

run(10);

It consistently "fails" with both, "fail" meaning that the close event is called before the end event. According to the documentation this should never happen.

The 'close' event is emitted when the stream and any of its underlying resources (a file descriptor, for example) have been closed. The event indicates that no more events will be emitted, and no further computation will occur.

NOTE: The number of setImmediates that you need to nest in order to make it "fail" may vary depending on your environment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions