@@ -34,7 +34,7 @@ internal abstract partial class IISHttpContext : NativeRequestContext, IThreadPo
34
34
private const int PauseWriterThreshold = 65536 ;
35
35
private const int ResumeWriterTheshold = PauseWriterThreshold / 2 ;
36
36
37
- protected readonly IntPtr _pInProcessHandler ;
37
+ protected readonly NativeSafeHandle _requestNativeHandle ;
38
38
39
39
private readonly IISServerOptions _options ;
40
40
@@ -75,15 +75,15 @@ internal abstract partial class IISHttpContext : NativeRequestContext, IThreadPo
75
75
76
76
internal unsafe IISHttpContext (
77
77
MemoryPool < byte > memoryPool ,
78
- IntPtr pInProcessHandler ,
78
+ NativeSafeHandle pInProcessHandler ,
79
79
IISServerOptions options ,
80
80
IISHttpServer server ,
81
81
ILogger logger ,
82
82
bool useLatin1 )
83
83
: base ( ( HttpApiTypes . HTTP_REQUEST * ) NativeMethods . HttpGetRawRequest ( pInProcessHandler ) , useLatin1 : useLatin1 )
84
84
{
85
85
_memoryPool = memoryPool ;
86
- _pInProcessHandler = pInProcessHandler ;
86
+ _requestNativeHandle = pInProcessHandler ;
87
87
_options = options ;
88
88
_server = server ;
89
89
_logger = logger ;
@@ -179,7 +179,7 @@ protected void InitializeContext()
179
179
180
180
ResetFeatureCollection ( ) ;
181
181
182
- if ( ! _server . IsWebSocketAvailable ( _pInProcessHandler ) )
182
+ if ( ! _server . IsWebSocketAvailable ( _requestNativeHandle ) )
183
183
{
184
184
_currentIHttpUpgradeFeature = null ;
185
185
}
@@ -198,7 +198,7 @@ protected void InitializeContext()
198
198
_bodyOutput = new OutputProducer ( pipe ) ;
199
199
}
200
200
201
- NativeMethods . HttpSetManagedContext ( _pInProcessHandler , ( IntPtr ) _thisHandle ) ;
201
+ NativeMethods . HttpSetManagedContext ( _requestNativeHandle , ( IntPtr ) _thisHandle ) ;
202
202
}
203
203
204
204
private string GetOriginalPath ( )
@@ -324,7 +324,7 @@ private void EnsureIOInitialized()
324
324
// If at this point request was not upgraded just start a normal IO engine
325
325
if ( AsyncIO == null )
326
326
{
327
- AsyncIO = new AsyncIOEngine ( _contextLock , _pInProcessHandler ) ;
327
+ AsyncIO = new AsyncIOEngine ( _contextLock , _requestNativeHandle ) ;
328
328
}
329
329
}
330
330
@@ -383,7 +383,7 @@ public unsafe void SetResponseHeaders()
383
383
var reasonPhrase = string . IsNullOrEmpty ( ReasonPhrase ) ? ReasonPhrases . GetReasonPhrase ( StatusCode ) : ReasonPhrase ;
384
384
385
385
// This copies data into the underlying buffer
386
- NativeMethods . HttpSetResponseStatusCode ( _pInProcessHandler , ( ushort ) StatusCode , reasonPhrase ) ;
386
+ NativeMethods . HttpSetResponseStatusCode ( _requestNativeHandle , ( ushort ) StatusCode , reasonPhrase ) ;
387
387
388
388
HttpResponseHeaders . IsReadOnly = true ;
389
389
foreach ( var headerPair in HttpResponseHeaders )
@@ -412,12 +412,12 @@ public unsafe void SetResponseHeaders()
412
412
var headerNameBytes = Encoding . UTF8 . GetBytes ( headerPair . Key ) ;
413
413
fixed ( byte * pHeaderName = headerNameBytes )
414
414
{
415
- NativeMethods . HttpResponseSetUnknownHeader ( _pInProcessHandler , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
415
+ NativeMethods . HttpResponseSetUnknownHeader ( _requestNativeHandle , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
416
416
}
417
417
}
418
418
else
419
419
{
420
- NativeMethods . HttpResponseSetKnownHeader ( _pInProcessHandler , knownHeaderIndex , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
420
+ NativeMethods . HttpResponseSetKnownHeader ( _requestNativeHandle , knownHeaderIndex , pHeaderValue , ( ushort ) headerValueBytes . Length , fReplace : isFirst ) ;
421
421
}
422
422
}
423
423
}
@@ -451,7 +451,7 @@ public unsafe void SetResponseTrailers()
451
451
var headerValueBytes = Encoding . UTF8 . GetBytes ( headerValue ) ;
452
452
fixed ( byte * pHeaderValue = headerValueBytes )
453
453
{
454
- NativeMethods . HttpResponseSetTrailer ( _pInProcessHandler , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , replace : isFirst ) ;
454
+ NativeMethods . HttpResponseSetTrailer ( _requestNativeHandle , pHeaderName , pHeaderValue , ( ushort ) headerValueBytes . Length , replace : isFirst ) ;
455
455
}
456
456
457
457
isFirst = false ;
@@ -576,8 +576,8 @@ protected void ReportApplicationError(Exception ex)
576
576
577
577
public void PostCompletion ( NativeMethods . REQUEST_NOTIFICATION_STATUS requestNotificationStatus )
578
578
{
579
- NativeMethods . HttpSetCompletionStatus ( _pInProcessHandler , requestNotificationStatus ) ;
580
- NativeMethods . HttpPostCompletion ( _pInProcessHandler , 0 ) ;
579
+ NativeMethods . HttpSetCompletionStatus ( _requestNativeHandle , requestNotificationStatus ) ;
580
+ NativeMethods . HttpPostCompletion ( _requestNativeHandle , 0 ) ;
581
581
}
582
582
583
583
internal void OnAsyncCompletion ( int hr , int bytes )
@@ -628,7 +628,7 @@ private void ThrowResponseAlreadyStartedException(string name)
628
628
629
629
private WindowsPrincipal GetWindowsPrincipal ( )
630
630
{
631
- NativeMethods . HttpGetAuthenticationInformation ( _pInProcessHandler , out var authenticationType , out var token ) ;
631
+ NativeMethods . HttpGetAuthenticationInformation ( _requestNativeHandle , out var authenticationType , out var token ) ;
632
632
633
633
if ( token != IntPtr . Zero && authenticationType != null )
634
634
{
@@ -664,6 +664,17 @@ private async Task HandleRequest()
664
664
// Post completion after completing the request to resume the state machine
665
665
PostCompletion ( ConvertRequestCompletionResults ( successfulRequest ) ) ;
666
666
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
+
667
678
// Dispose the context
668
679
Dispose ( ) ;
669
680
}
0 commit comments