@@ -26,6 +26,10 @@ const util = require('util');
2626const EventEmitter = require ( 'events' ) ;
2727const debug = util . debuglog ( 'http' ) ;
2828const { async_id_symbol } = require ( 'internal/async_hooks' ) . symbols ;
29+ const errors = require ( 'internal/errors' ) ;
30+ const {
31+ ERR_HTTP_SOCKET_TIMEOUT ,
32+ } = errors . codes ;
2933
3034// New Agent code.
3135
@@ -268,6 +272,24 @@ function installListeners(agent, s, options) {
268272 }
269273 s . on ( 'close' , onClose ) ;
270274
275+ function onTimeout ( ) {
276+ debug ( 'CLIENT socket onTimeout after' , s . timeout , 'ms' ) ;
277+ const name = agent . getName ( options ) ;
278+ // If free socket timeout, must remove it from freeSockets list immediately
279+ // to prevent new requests from being sent through this timeout socket.
280+ if ( agent . freeSockets [ name ] && agent . freeSockets [ name ] . indexOf ( s ) !== - 1 ) {
281+ s . destroy ( ) ;
282+ agent . removeSocket ( s , options ) ;
283+ debug ( 'CLIENT free socket destroy' ) ;
284+ } else if ( s . listeners ( 'timeout' ) . length === 1 ) {
285+ // No req timeout handler, agent must destroy the socket.
286+ s . destroy ( new ERR_HTTP_SOCKET_TIMEOUT ( ) ) ;
287+ agent . removeSocket ( s , options ) ;
288+ debug ( 'CLIENT active socket destroy' ) ;
289+ }
290+ }
291+ s . on ( 'timeout' , onTimeout ) ;
292+
271293 function onRemove ( ) {
272294 // We need this function for cases like HTTP 'upgrade'
273295 // (defined by WebSockets) where we need to remove a socket from the
@@ -276,6 +298,7 @@ function installListeners(agent, s, options) {
276298 agent . removeSocket ( s , options ) ;
277299 s . removeListener ( 'close' , onClose ) ;
278300 s . removeListener ( 'free' , onFree ) ;
301+ s . removeListener ( 'timeout' , onTimeout ) ;
279302 s . removeListener ( 'agentRemove' , onRemove ) ;
280303 }
281304 s . on ( 'agentRemove' , onRemove ) ;
0 commit comments