@@ -673,15 +673,23 @@ function submitShutdown(options) {
673673}
674674
675675function finishSessionDestroy ( socket ) {
676+ const state = this [ kState ] ;
677+ if ( state . destroyed )
678+ return ;
679+
676680 if ( ! socket . destroyed )
677681 socket . destroy ( ) ;
678682
683+ state . destroying = false ;
684+ state . destroyed = true ;
685+
679686 // Destroy the handle
680687 const handle = this [ kHandle ] ;
681688 if ( handle !== undefined ) {
682- handle . destroy ( ) ;
689+ handle . destroy ( state . skipUnconsume ) ;
683690 debug ( `[${ sessionName ( this [ kType ] ) } ] nghttp2session handle destroyed` ) ;
684691 }
692+ this [ kHandle ] = undefined ;
685693
686694 process . nextTick ( emit . bind ( this , 'close' ) ) ;
687695 debug ( `[${ sessionName ( this [ kType ] ) } ] nghttp2session destroyed` ) ;
@@ -825,7 +833,7 @@ class Http2Session extends EventEmitter {
825833
826834 // Submits a SETTINGS frame to be sent to the remote peer.
827835 settings ( settings ) {
828- if ( this [ kState ] . destroyed )
836+ if ( this [ kState ] . destroyed || this [ kState ] . destroying )
829837 throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
830838
831839 // Validate the input first
@@ -871,7 +879,7 @@ class Http2Session extends EventEmitter {
871879
872880 // Submits a PRIORITY frame to be sent to the remote peer.
873881 priority ( stream , options ) {
874- if ( this [ kState ] . destroyed )
882+ if ( this [ kState ] . destroyed || this [ kState ] . destroying )
875883 throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
876884
877885 if ( ! ( stream instanceof Http2Stream ) ) {
@@ -905,6 +913,8 @@ class Http2Session extends EventEmitter {
905913 // Submits an RST-STREAM frame to be sent to the remote peer. This will
906914 // cause the stream to be closed.
907915 rstStream ( stream , code = NGHTTP2_NO_ERROR ) {
916+ // Do not check destroying here, as the rstStream may be sent while
917+ // the session is in the middle of being destroyed.
908918 if ( this [ kState ] . destroyed )
909919 throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
910920
@@ -946,7 +956,6 @@ class Http2Session extends EventEmitter {
946956 const state = this [ kState ] ;
947957 if ( state . destroyed || state . destroying )
948958 return ;
949-
950959 debug ( `[${ sessionName ( this [ kType ] ) } ] destroying nghttp2session` ) ;
951960 state . destroying = true ;
952961
@@ -963,8 +972,8 @@ class Http2Session extends EventEmitter {
963972 delete this [ kSocket ] ;
964973 delete this [ kServer ] ;
965974
966- state . destroyed = true ;
967- state . destroying = false ;
975+ state . destroyed = false ;
976+ state . destroying = true ;
968977
969978 if ( this [ kHandle ] !== undefined )
970979 this [ kHandle ] . destroying ( ) ;
@@ -975,7 +984,7 @@ class Http2Session extends EventEmitter {
975984 // Graceful or immediate shutdown of the Http2Session. Graceful shutdown
976985 // is only supported on the server-side
977986 shutdown ( options , callback ) {
978- if ( this [ kState ] . destroyed )
987+ if ( this [ kState ] . destroyed || this [ kState ] . destroying )
979988 throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
980989
981990 if ( this [ kState ] . shutdown || this [ kState ] . shuttingDown )
@@ -1037,7 +1046,7 @@ class Http2Session extends EventEmitter {
10371046 }
10381047
10391048 _onTimeout ( ) {
1040- this . emit ( 'timeout' ) ;
1049+ process . nextTick ( emit . bind ( this , 'timeout' ) ) ;
10411050 }
10421051}
10431052
@@ -1061,7 +1070,7 @@ class ClientHttp2Session extends Http2Session {
10611070 // Submits a new HTTP2 request to the connected peer. Returns the
10621071 // associated Http2Stream instance.
10631072 request ( headers , options ) {
1064- if ( this [ kState ] . destroyed )
1073+ if ( this [ kState ] . destroyed || this [ kState ] . destroying )
10651074 throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
10661075 debug ( `[${ sessionName ( this [ kType ] ) } ] initiating request` ) ;
10671076 _unrefActive ( this ) ;
@@ -1317,7 +1326,7 @@ class Http2Stream extends Duplex {
13171326 }
13181327
13191328 _onTimeout ( ) {
1320- this . emit ( 'timeout' ) ;
1329+ process . nextTick ( emit . bind ( this , 'timeout' ) ) ;
13211330 }
13221331
13231332 // true if the Http2Stream was aborted abornomally.
@@ -2104,7 +2113,7 @@ const onTimeout = {
21042113 configurable : false ,
21052114 enumerable : false ,
21062115 value : function ( ) {
2107- this . emit ( 'timeout' ) ;
2116+ process . nextTick ( emit . bind ( this , 'timeout' ) ) ;
21082117 }
21092118} ;
21102119
@@ -2191,20 +2200,22 @@ function socketOnError(error) {
21912200// of the session.
21922201function socketOnTimeout ( ) {
21932202 debug ( 'socket timeout' ) ;
2194- const server = this [ kServer ] ;
2195- const session = this [ kSession ] ;
2196- // If server or session are undefined, then we're already in the process of
2197- // shutting down, do nothing.
2198- if ( server === undefined || session === undefined )
2199- return ;
2200- if ( ! server . emit ( 'timeout' , session , this ) ) {
2201- session . shutdown (
2202- {
2203- graceful : true ,
2204- errorCode : NGHTTP2_NO_ERROR
2205- } ,
2206- this . destroy . bind ( this ) ) ;
2207- }
2203+ process . nextTick ( ( ) => {
2204+ const server = this [ kServer ] ;
2205+ const session = this [ kSession ] ;
2206+ // If server or session are undefined, then we're already in the process of
2207+ // shutting down, do nothing.
2208+ if ( server === undefined || session === undefined )
2209+ return ;
2210+ if ( ! server . emit ( 'timeout' , session , this ) ) {
2211+ session . shutdown (
2212+ {
2213+ graceful : true ,
2214+ errorCode : NGHTTP2_NO_ERROR
2215+ } ,
2216+ this . destroy . bind ( this ) ) ;
2217+ }
2218+ } ) ;
22082219}
22092220
22102221// Handles the on('stream') event for a session and forwards
@@ -2346,6 +2357,8 @@ function setupCompat(ev) {
23462357function socketOnClose ( hadError ) {
23472358 const session = this [ kSession ] ;
23482359 if ( session !== undefined && ! session . destroyed ) {
2360+ // Skip unconsume because the socket is destroyed.
2361+ session [ kState ] . skipUnconsume = true ;
23492362 session . destroy ( ) ;
23502363 }
23512364}
0 commit comments