@@ -34,7 +34,7 @@ internal abstract partial class IISHttpContext : NativeRequestContext, IThreadPo
3434 private const int PauseWriterThreshold = 65536 ;
3535 private const int ResumeWriterTheshold = PauseWriterThreshold / 2 ;
3636
37- protected readonly IntPtr _pInProcessHandler ;
37+ protected readonly NativeSafeHandle _requestNativeHandle ;
3838
3939 private readonly IISServerOptions _options ;
4040
@@ -75,15 +75,15 @@ internal abstract partial class IISHttpContext : NativeRequestContext, IThreadPo
7575
7676 internal unsafe IISHttpContext (
7777 MemoryPool < byte > memoryPool ,
78- IntPtr pInProcessHandler ,
78+ NativeSafeHandle pInProcessHandler ,
7979 IISServerOptions options ,
8080 IISHttpServer server ,
8181 ILogger logger ,
8282 bool useLatin1 )
8383 : base ( ( HttpApiTypes . HTTP_REQUEST * ) NativeMethods . HttpGetRawRequest ( pInProcessHandler ) , useLatin1 : useLatin1 )
8484 {
8585 _memoryPool = memoryPool ;
86- _pInProcessHandler = pInProcessHandler ;
86+ _requestNativeHandle = pInProcessHandler ;
8787 _options = options ;
8888 _server = server ;
8989 _logger = logger ;
@@ -179,7 +179,7 @@ protected void InitializeContext()
179179
180180 ResetFeatureCollection ( ) ;
181181
182- if ( ! _server . IsWebSocketAvailable ( _pInProcessHandler ) )
182+ if ( ! _server . IsWebSocketAvailable ( _requestNativeHandle ) )
183183 {
184184 _currentIHttpUpgradeFeature = null ;
185185 }
@@ -198,7 +198,7 @@ protected void InitializeContext()
198198 _bodyOutput = new OutputProducer ( pipe ) ;
199199 }
200200
201- NativeMethods . HttpSetManagedContext ( _pInProcessHandler , ( IntPtr ) _thisHandle ) ;
201+ NativeMethods . HttpSetManagedContext ( _requestNativeHandle , ( IntPtr ) _thisHandle ) ;
202202 }
203203
204204 private string GetOriginalPath ( )
@@ -324,7 +324,7 @@ private void EnsureIOInitialized()
324324 // If at this point request was not upgraded just start a normal IO engine
325325 if ( AsyncIO == null )
326326 {
327- AsyncIO = new AsyncIOEngine ( _contextLock , _pInProcessHandler ) ;
327+ AsyncIO = new AsyncIOEngine ( _contextLock , _requestNativeHandle ) ;
328328 }
329329 }
330330
@@ -383,7 +383,7 @@ public unsafe void SetResponseHeaders()
383383 var reasonPhrase = string . IsNullOrEmpty ( ReasonPhrase ) ? ReasonPhrases . GetReasonPhrase ( StatusCode ) : ReasonPhrase ;
384384
385385 // This copies data into the underlying buffer
386- NativeMethods . HttpSetResponseStatusCode ( _pInProcessHandler , ( ushort ) StatusCode , reasonPhrase ) ;
386+ NativeMethods . HttpSetResponseStatusCode ( _requestNativeHandle , ( ushort ) StatusCode , reasonPhrase ) ;
387387
388388 HttpResponseHeaders . IsReadOnly = true ;
389389 foreach ( var headerPair in HttpResponseHeaders )
@@ -412,12 +412,12 @@ public unsafe void SetResponseHeaders()
412412 var headerNameBytes = Encoding . UTF8 . GetBytes ( headerPair . Key ) ;
413413 fixed ( byte * pHeaderName = headerNameBytes )
414414 {
415- NativeMethods . HttpResponseSetUnknownHeader ( _pInProcessHandler , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
415+ NativeMethods . HttpResponseSetUnknownHeader ( _requestNativeHandle , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
416416 }
417417 }
418418 else
419419 {
420- NativeMethods . HttpResponseSetKnownHeader ( _pInProcessHandler , knownHeaderIndex , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
420+ NativeMethods . HttpResponseSetKnownHeader ( _requestNativeHandle , knownHeaderIndex , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
421421 }
422422 }
423423 }
@@ -451,7 +451,7 @@ public unsafe void SetResponseTrailers()
451451 var headerValueBytes = Encoding . UTF8 . GetBytes ( headerValue ) ;
452452 fixed ( byte * pHeaderValue = headerValueBytes )
453453 {
454- NativeMethods . HttpResponseSetTrailer ( _pInProcessHandler , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , replace : isFirst ) ;
454+ NativeMethods . HttpResponseSetTrailer ( _requestNativeHandle , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , replace : isFirst ) ;
455455 }
456456
457457 isFirst = false ;
@@ -576,8 +576,8 @@ protected void ReportApplicationError(Exception ex)
576576
577577 public void PostCompletion ( NativeMethods . REQUEST_NOTIFICATION_STATUS requestNotificationStatus )
578578 {
579- NativeMethods . HttpSetCompletionStatus ( _pInProcessHandler , requestNotificationStatus ) ;
580- NativeMethods . HttpPostCompletion ( _pInProcessHandler , 0 ) ;
579+ NativeMethods . HttpSetCompletionStatus ( _requestNativeHandle , requestNotificationStatus ) ;
580+ NativeMethods . HttpPostCompletion ( _requestNativeHandle , 0 ) ;
581581 }
582582
583583 internal void OnAsyncCompletion ( int hr , int bytes )
@@ -628,7 +628,7 @@ private void ThrowResponseAlreadyStartedException(string name)
628628
629629 private WindowsPrincipal GetWindowsPrincipal ( )
630630 {
631- NativeMethods . HttpGetAuthenticationInformation ( _pInProcessHandler , out var authenticationType , out var token ) ;
631+ NativeMethods . HttpGetAuthenticationInformation ( _requestNativeHandle , out var authenticationType , out var token ) ;
632632
633633 if ( token != IntPtr . Zero && authenticationType != null )
634634 {
@@ -664,6 +664,17 @@ private async Task HandleRequest()
664664 // Post completion after completing the request to resume the state machine
665665 PostCompletion ( ConvertRequestCompletionResults ( successfulRequest ) ) ;
666666
667+ // After disposing a safe handle, Dispose() will not block waiting for the pinvokes to finish.
668+ // Instead Safehandle will call ReleaseHandle on the pinvoke thread when the pinvokes complete
669+ // and the reference count goes to zero.
670+
671+ // What this means is we need to wait until ReleaseHandle is called to finish disposal.
672+ // This is to make sure it is safe to return back to native.
673+ // The handle implements IValueTaskSource
674+ _requestNativeHandle . Dispose ( ) ;
675+
676+ await new ValueTask < object > ( _requestNativeHandle , _requestNativeHandle . Version ) ;
677+
667678 // Dispose the context
668679 Dispose ( ) ;
669680 }
0 commit comments