Skip to content

Close event of net.Socket is not emitted if internalConnectMultipleTimeout is triggered #48426

Closed
@ZEDCWT

Description

@ZEDCWT

Version

v20.3.0

Platform

Linux Square 5.15.0-73-generic #80-Ubuntu SMP Mon May 15 15:18:26 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

require('net').connect(443,'eva.csdn.net')
	.once('connect',() => console.log('CONN'))
	.once('error',E => console.log('ERR',E))
	.once('close',() => console.log('CLOSE'))

How often does it reproduce? Is there a required condition?

For a certain network environment and a certain target domain, always

What is the expected behavior? Why is that the expected behavior?

It either ouputs CONN or ERR ... followed by CLOSE

What do you see instead?

Since it only fails on one of my device, here is the output with envvar NODE_DEBUG=net

NET 20825: createConnection [
  { port: 443, host: 'eva.csdn.net' },
  null,
  [Symbol(normalizedArgs)]: true
]
NET 20825: pipe false undefined
NET 20825: connect: find host eva.csdn.net
NET 20825: connect: dns options { family: undefined, hints: 32 }
NET 20825: connect: autodetecting
NET 20825: connect/multiple: will try the following addresses [
  { address: '49.4.17.138', family: 4 },
  { address: '2407:c080:1400:57:f85b:6894:e943:69b1', family: 6 },
  { address: '49.4.45.146', family: 4 },
  { address: '2407:c080:1400:57:867a:db36:8b28:473f', family: 6 }
]
NET 20825: connect/multiple: attempting to connect to 49.4.17.138:443 (addressType: 4)
NET 20825: connect/multiple: setting the attempt timeout to 250 ms
NET 20825: connect/multiple: connection to 49.4.17.138:443 timed out
NET 20825: connect/multiple: attempting to connect to 2407:c080:1400:57:f85b:6894:e943:69b1:443 (addressType: 6)
NET 20825: connect/multiple: attempting to connect to 49.4.45.146:443 (addressType: 4)
NET 20825: connect/multiple: setting the attempt timeout to 250 ms
NET 20825: connect/multiple: connection to 49.4.45.146:443 timed out
NET 20825: connect/multiple: attempting to connect to 2407:c080:1400:57:867a:db36:8b28:473f:443 (addressType: 6)
NET 20825: destroy
NET 20825: close
NET 20825: close handle
ERR AggregateError
    at internalConnectMultiple (node:net:1102:18)
    at internalConnectMultiple (node:net:1161:5)
    at Timeout.internalConnectMultipleTimeout (node:net:1644:3)
    at listOnTimeout (node:internal/timers:575:11)
    at process.processTimers (node:internal/timers:514:7) {
  code: 'ENETUNREACH',
  [errors]: [
    Error: connect ENETUNREACH 2407:c080:1400:57:f85b:6894:e943:69b1:443 - Local (undefined:undefined)
        at internalConnectMultiple (node:net:1160:40)
        at Timeout.internalConnectMultipleTimeout (node:net:1644:3)
        at listOnTimeout (node:internal/timers:575:11)
        at process.processTimers (node:internal/timers:514:7) {
      errno: -101,
      code: 'ENETUNREACH',
      syscall: 'connect',
      address: '2407:c080:1400:57:f85b:6894:e943:69b1',
      port: 443
    },
    Error: connect ENETUNREACH 2407:c080:1400:57:867a:db36:8b28:473f:443 - Local (undefined:undefined)
        at internalConnectMultiple (node:net:1160:40)
        at Timeout.internalConnectMultipleTimeout (node:net:1644:3)
        at listOnTimeout (node:internal/timers:575:11)
        at process.processTimers (node:internal/timers:514:7) {
      errno: -101,
      code: 'ENETUNREACH',
      syscall: 'connect',
      address: '2407:c080:1400:57:867a:db36:8b28:473f',
      port: 443
    }
  ]
}

The CLOSE is not outputted

Additional information

Reading the document, it says

Event: 'error'#
Added in: v0.1.90
Emitted when an error occurs. The 'close' event will be called directly following this event.

So I am expecting 'close' event to be emitted whenever 'error' occurred.

To debug the RC, here is the script I run

var
S = require('net').connect(443,'eva.csdn.net')
	.once('connect',() => console.log('CONN'))
	.once('error',E => console.log('ERR',E))
	.once('close',() => console.log('CLOSE')),
Close = S._handle.close;
S._handle.close = function(Q)
{
	console.log('Handle Close',Q)
	Close.call(this,...Q)
}

And here is what i got

NET 21124: connect/multiple: attempting to connect to 49.4.45.146:443 (addressType: 4)
NET 21124: connect/multiple: setting the attempt timeout to 250 ms
NET 21124: connect/multiple: connection to 49.4.45.146:443 timed out
Handle Close []
NET 21124: connect/multiple: attempting to connect to 2407:c080:1400:57:f85b:6894:e943:69b1:443 (addressType: 6)
NET 21124: connect/multiple: attempting to connect to 49.4.17.138:443 (addressType: 4)
NET 21124: connect/multiple: setting the attempt timeout to 250 ms
NET 21124: connect/multiple: connection to 49.4.17.138:443 timed out
NET 21124: connect/multiple: attempting to connect to 2407:c080:1400:57:867a:db36:8b28:473f:443 (addressType: 6)
NET 21124: destroy
NET 21124: close
NET 21124: close handle
Handle Close [ [Function (anonymous)] ]
ERR AggregateError

Now it becomes clear that internalConnectMultipleTimeout includes a handle.close() call that suppresses the callback of close in closeSocketHandle

Metadata

Metadata

Assignees

No one assigned

    Labels

    netIssues and PRs related to the net subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions