@@ -28,14 +28,14 @@ public class HttpConnectionContext : ConnectionContext,
28
28
IHttpTransportFeature ,
29
29
IConnectionInherentKeepAliveFeature
30
30
{
31
+ private readonly object _stateLock = new object ( ) ;
31
32
private readonly object _itemsLock = new object ( ) ;
32
33
private readonly object _heartbeatLock = new object ( ) ;
33
34
private List < ( Action < object > handler , object state ) > _heartbeatHandlers ;
34
35
private readonly ILogger _logger ;
35
36
private PipeWriterStream _applicationStream ;
36
37
private IDuplexPipe _application ;
37
38
private IDictionary < object , object > _items ;
38
- private int _status = ( int ) HttpConnectionStatus . Inactive ;
39
39
40
40
// This tcs exists so that multiple calls to DisposeAsync all wait asynchronously
41
41
// on the same task
@@ -83,7 +83,6 @@ public HttpConnectionContext(string id, IDuplexPipe transport, IDuplexPipe appli
83
83
public HttpTransportType TransportType { get ; set ; }
84
84
85
85
public SemaphoreSlim WriteLock { get ; } = new SemaphoreSlim ( 1 , 1 ) ;
86
- public SemaphoreSlim StateLock { get ; } = new SemaphoreSlim ( 1 , 1 ) ;
87
86
88
87
// Used for testing only
89
88
internal Task DisposeAndRemoveTask { get ; set ; }
@@ -96,7 +95,18 @@ public HttpConnectionContext(string id, IDuplexPipe transport, IDuplexPipe appli
96
95
97
96
public DateTime LastSeenUtc { get ; set ; }
98
97
99
- public HttpConnectionStatus Status { get => ( HttpConnectionStatus ) _status ; set => Interlocked . Exchange ( ref _status , ( int ) value ) ; }
98
+ public DateTime ? LastSeenUtcIfInactive
99
+ {
100
+ get
101
+ {
102
+ lock ( _stateLock )
103
+ {
104
+ return Status == HttpConnectionStatus . Inactive ? ( DateTime ? ) LastSeenUtc : null ;
105
+ }
106
+ }
107
+ }
108
+
109
+ public HttpConnectionStatus Status { get ; set ; } = HttpConnectionStatus . Inactive ;
100
110
101
111
public override string ConnectionId { get ; set ; }
102
112
@@ -184,29 +194,29 @@ public async Task DisposeAsync(bool closeGracefully = false)
184
194
{
185
195
Task disposeTask ;
186
196
187
- await StateLock . WaitAsync ( ) ;
188
197
try
189
198
{
190
- if ( Status == HttpConnectionStatus . Disposed )
199
+ lock ( _stateLock )
191
200
{
192
- disposeTask = _disposeTcs . Task ;
193
- }
194
- else
195
- {
196
- Status = HttpConnectionStatus . Disposed ;
201
+ if ( Status == HttpConnectionStatus . Disposed )
202
+ {
203
+ disposeTask = _disposeTcs . Task ;
204
+ }
205
+ else
206
+ {
207
+ Status = HttpConnectionStatus . Disposed ;
197
208
198
- Log . DisposingConnection ( _logger , ConnectionId ) ;
209
+ Log . DisposingConnection ( _logger , ConnectionId ) ;
199
210
200
- var applicationTask = ApplicationTask ?? Task . CompletedTask ;
201
- var transportTask = TransportTask ?? Task . CompletedTask ;
211
+ var applicationTask = ApplicationTask ?? Task . CompletedTask ;
212
+ var transportTask = TransportTask ?? Task . CompletedTask ;
202
213
203
- disposeTask = WaitOnTasks ( applicationTask , transportTask , closeGracefully ) ;
214
+ disposeTask = WaitOnTasks ( applicationTask , transportTask , closeGracefully ) ;
215
+ }
204
216
}
205
217
}
206
218
finally
207
219
{
208
- StateLock . Release ( ) ;
209
-
210
220
Cancellation ? . Dispose ( ) ;
211
221
212
222
Cancellation = null ;
@@ -310,9 +320,31 @@ private async Task WaitOnTasks(Task applicationTask, Task transportTask, bool cl
310
320
}
311
321
}
312
322
313
- public bool TryChangeState ( HttpConnectionStatus from , HttpConnectionStatus to )
323
+ public HttpConnectionStatus TryChangeState ( HttpConnectionStatus from , HttpConnectionStatus to )
314
324
{
315
- return Interlocked . CompareExchange ( ref _status , ( int ) to , ( int ) from ) == ( int ) from ;
325
+ lock ( _stateLock )
326
+ {
327
+ if ( Status == from )
328
+ {
329
+ Status = to ;
330
+ return from ;
331
+ }
332
+
333
+ return Status ;
334
+ }
335
+ }
336
+
337
+ public void MarkInactive ( )
338
+ {
339
+ lock ( _stateLock )
340
+ {
341
+ LastSeenUtc = DateTime . UtcNow ;
342
+
343
+ if ( Status == HttpConnectionStatus . Active )
344
+ {
345
+ Status = HttpConnectionStatus . Inactive ;
346
+ }
347
+ }
316
348
}
317
349
318
350
private static class Log
0 commit comments