Skip to content

Commit 95aec0a

Browse files
committed
Fixed issue with CloseAsync (taking too much time to resolve)
1 parent 43099cf commit 95aec0a

11 files changed

+112
-151
lines changed

src/Unosquare.Labs.EmbedIO/System.Net/EndPointListener.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void UnbindContext(HttpListenerContext context)
103103
context.Listener.UnregisterContext(context);
104104
}
105105

106-
public async Task CloseAsync()
106+
public void Close()
107107
{
108108
_sock.Dispose();
109109
List<HttpConnection> connections;
@@ -116,7 +116,7 @@ public async Task CloseAsync()
116116
}
117117

118118
foreach (var c in connections)
119-
await c.CloseAsync(true);
119+
c.Close(true);
120120
}
121121

122122
public void AddPrefix(ListenerPrefix prefix, HttpListener listener)
@@ -286,7 +286,7 @@ private static void ProcessAccept(SocketAsyncEventArgs args)
286286
epl._unregistered[conn] = conn;
287287
}
288288

289-
conn.BeginReadRequest().Wait();
289+
var waitTask = conn.BeginReadRequest();
290290
}
291291

292292
private static void OnAccept(object sender, SocketAsyncEventArgs e) => ProcessAccept(e);

src/Unosquare.Labs.EmbedIO/System.Net/EndPointManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ public static void RemoveEndPoint(EndPointListener epl, IPEndPoint ep)
8080
IPToEndpoints.Remove(ep.Address);
8181
}
8282
}
83-
84-
epl.CloseAsync().Wait(); // TODO: Is this right?
83+
84+
epl.Close();
8585
}
8686

8787
public static void RemoveListener(HttpListener listener)

src/Unosquare.Labs.EmbedIO/System.Net/HttpConnection.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,11 @@ public ResponseStream GetResponseStream()
189189
new ResponseStream(Stream, _context.Response, _context.Listener?.IgnoreWriteExceptions ?? true));
190190
}
191191

192-
internal async Task CloseAsync(bool forceClose = false)
192+
internal void Close(bool forceClose = false)
193193
{
194194
if (_sock != null)
195195
{
196-
Stream st = GetResponseStream();
197-
st?.Dispose();
196+
GetResponseStream()?.Dispose();
198197

199198
_oStream = null;
200199
}
@@ -208,14 +207,14 @@ internal async Task CloseAsync(bool forceClose = false)
208207

209208
if (!forceClose)
210209
{
211-
var isValidInput = await _context.Request.FlushInput();
212-
213-
if (isValidInput)
210+
if (_context.Request.FlushInput().GetAwaiter().GetResult())
214211
{
215212
Reuses++;
216213
Unbind();
217214
Init();
218-
await BeginReadRequest().ConfigureAwait(false);
215+
#pragma warning disable 4014
216+
BeginReadRequest();
217+
#pragma warning restore 4014
219218
return;
220219
}
221220
}
@@ -280,7 +279,7 @@ private async Task OnReadInternal(int nread)
280279
await _ms.WriteAsync(_buffer, parsedBytes, nread - parsedBytes);
281280
if (_ms.Length > 32768)
282281
{
283-
await CloseAsync(true);
282+
Close(true);
284283
return;
285284
}
286285
}
@@ -307,7 +306,7 @@ private async Task OnReadInternal(int nread)
307306

308307
if (_context.HaveError || !_epl.BindContext(_context))
309308
{
310-
await CloseAsync(true);
309+
Close(true);
311310
return;
312311
}
313312

src/Unosquare.Labs.EmbedIO/System.Net/HttpListener.cs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,12 @@ internal IMonoSslStream CreateSslStream(Stream innerStream, bool ownsStream, MSI
161161
/// <summary>
162162
/// Aborts this listener.
163163
/// </summary>
164-
/// <returns>The task aborting</returns>
165-
public Task AbortAsync() => CloseAsync();
164+
public void Abort() => Close();
166165

167166
/// <summary>
168167
/// Closes this listener.
169168
/// </summary>
170-
/// <returns>The task closing</returns>
171-
public async Task CloseAsync()
169+
public void Close()
172170
{
173171
if (_disposed)
174172
return;
@@ -179,7 +177,7 @@ public async Task CloseAsync()
179177
return;
180178
}
181179

182-
await CloseAsync(true);
180+
Close(true);
183181
_disposed = true;
184182
}
185183

@@ -198,19 +196,18 @@ public void Start()
198196
/// <summary>
199197
/// Stops this listener.
200198
/// </summary>
201-
/// <returns>The task stopping the listener</returns>
202-
public Task StopAsync()
199+
public void Stop()
203200
{
204201
IsListening = false;
205-
return CloseAsync(false);
202+
Close(false);
206203
}
207204

208205
void IDisposable.Dispose()
209206
{
210207
if (_disposed)
211208
return;
212-
213-
CloseAsync(true).Wait();
209+
210+
Close(true);
214211
_disposed = true;
215212
}
216213

@@ -224,7 +221,7 @@ public async Task<HttpListenerContext> GetContextAsync()
224221
{
225222
foreach (var key in _ctxQueue.Keys)
226223
{
227-
if (_ctxQueue.TryRemove(key, out HttpListenerContext context))
224+
if (_ctxQueue.TryRemove(key, out var context))
228225
return context;
229226
}
230227

@@ -240,20 +237,14 @@ internal void RegisterContext(HttpListenerContext context)
240237

241238
internal void UnregisterContext(HttpListenerContext context)
242239
{
243-
_ctxQueue.TryRemove(context.Id, out HttpListenerContext removedContext);
240+
_ctxQueue.TryRemove(context.Id, out var removedContext);
244241
}
245242

246-
internal void AddConnection(HttpConnection cnc)
247-
{
248-
_connections[cnc] = cnc;
249-
}
243+
internal void AddConnection(HttpConnection cnc) => _connections[cnc] = cnc;
250244

251-
internal void RemoveConnection(HttpConnection cnc)
252-
{
253-
_connections.Remove(cnc);
254-
}
245+
internal void RemoveConnection(HttpConnection cnc) => _connections.Remove(cnc);
255246

256-
private async Task CloseAsync(bool closeExisting)
247+
private void Close(bool closeExisting)
257248
{
258249
EndPointManager.RemoveListener(this);
259250

@@ -269,16 +260,16 @@ private async Task CloseAsync(bool closeExisting)
269260
}
270261

271262
for (var i = conns.Count - 1; i >= 0; i--)
272-
await conns[i].CloseAsync(true).ConfigureAwait(false);
263+
conns[i].Close(true);
273264

274265
if (closeExisting == false) return;
275266

276267
while (_ctxQueue.IsEmpty == false)
277268
{
278269
foreach (var key in _ctxQueue.Keys.Select(x => x).ToList())
279270
{
280-
if (_ctxQueue.TryGetValue(key, out HttpListenerContext context))
281-
await context.Connection.CloseAsync(true).ConfigureAwait(false);
271+
if (_ctxQueue.TryGetValue(key, out var context))
272+
context.Connection.Close(true);
282273
}
283274
}
284275
}

src/Unosquare.Labs.EmbedIO/System.Net/HttpListenerRequest.cs

Lines changed: 65 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,10 @@ internal void FinishInitialization()
377377
return;
378378
}
379379

380-
string path;
381380
Uri rawUri = null;
382-
if (RawUrl.ToLowerInvariant().MaybeUri() && Uri.TryCreate(RawUrl, UriKind.Absolute, out rawUri))
383-
path = rawUri.PathAndQuery;
384-
else
385-
path = RawUrl;
381+
var path = RawUrl.ToLowerInvariant().MaybeUri() && Uri.TryCreate(RawUrl, UriKind.Absolute, out rawUri)
382+
? rawUri.PathAndQuery
383+
: RawUrl;
386384

387385
if (string.IsNullOrEmpty(host))
388386
host = UserHostAddress;
@@ -420,8 +418,7 @@ internal void FinishInitialization()
420418

421419
if (string.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0)
422420
{
423-
var output = _context.Connection.GetResponseStream();
424-
output.InternalWrite(_100Continue, 0, _100Continue.Length);
421+
_context.Connection.GetResponseStream().InternalWrite(_100Continue, 0, _100Continue.Length);
425422
}
426423
}
427424

@@ -437,10 +434,10 @@ internal void AddHeader(string header)
437434

438435
var name = header.Substring(0, colon).Trim();
439436
var val = header.Substring(colon + 1).Trim();
440-
var lower = name.ToLowerInvariant();
437+
441438
Headers.Set(name, val);
442439

443-
switch (lower)
440+
switch (name.ToLowerInvariant())
444441
{
445442
case "accept-language":
446443
UserLanguages = val.Split(Labs.EmbedIO.Constants.Strings.CommaSplitChar); // yes, only split with a ','
@@ -475,60 +472,7 @@ internal void AddHeader(string header)
475472

476473
break;
477474
case "cookie":
478-
if (_cookies == null)
479-
_cookies = new CookieCollection();
480-
481-
var cookieStrings = val.Split(Labs.EmbedIO.Constants.Strings.CookieSplitChars)
482-
.Where(x => string.IsNullOrEmpty(x) == false);
483-
Cookie current = null;
484-
var version = 0;
485-
486-
foreach (var str in cookieStrings)
487-
{
488-
if (str.StartsWith("$Version"))
489-
{
490-
version = int.Parse(str.Substring(str.IndexOf('=') + 1).Unquote());
491-
}
492-
else if (str.StartsWith("$Path") && current != null)
493-
{
494-
current.Path = str.Substring(str.IndexOf('=') + 1).Trim();
495-
}
496-
else if (str.StartsWith("$Domain") && current != null)
497-
{
498-
current.Domain = str.Substring(str.IndexOf('=') + 1).Trim();
499-
}
500-
else if (str.StartsWith("$Port") && current != null)
501-
{
502-
current.Port = str.Substring(str.IndexOf('=') + 1).Trim();
503-
}
504-
else
505-
{
506-
if (current != null)
507-
{
508-
_cookies.Add(current);
509-
}
510-
511-
current = new Cookie();
512-
var idx = str.IndexOf('=');
513-
if (idx > 0)
514-
{
515-
current.Name = str.Substring(0, idx).Trim();
516-
current.Value = str.Substring(idx + 1).Trim();
517-
}
518-
else
519-
{
520-
current.Name = str.Trim();
521-
current.Value = string.Empty;
522-
}
523-
524-
current.Version = version;
525-
}
526-
}
527-
528-
if (current != null)
529-
{
530-
_cookies.Add(current);
531-
}
475+
ParseCookies(val);
532476

533477
break;
534478
}
@@ -566,6 +510,64 @@ internal async Task<bool> FlushInput()
566510
}
567511
}
568512
}
513+
514+
private void ParseCookies(string val)
515+
{
516+
if (_cookies == null)
517+
_cookies = new CookieCollection();
518+
519+
var cookieStrings = val.Split(Labs.EmbedIO.Constants.Strings.CookieSplitChars)
520+
.Where(x => string.IsNullOrEmpty(x) == false);
521+
Cookie current = null;
522+
var version = 0;
523+
524+
foreach (var str in cookieStrings)
525+
{
526+
if (str.StartsWith("$Version"))
527+
{
528+
version = int.Parse(str.Substring(str.IndexOf('=') + 1).Unquote());
529+
}
530+
else if (str.StartsWith("$Path") && current != null)
531+
{
532+
current.Path = str.Substring(str.IndexOf('=') + 1).Trim();
533+
}
534+
else if (str.StartsWith("$Domain") && current != null)
535+
{
536+
current.Domain = str.Substring(str.IndexOf('=') + 1).Trim();
537+
}
538+
else if (str.StartsWith("$Port") && current != null)
539+
{
540+
current.Port = str.Substring(str.IndexOf('=') + 1).Trim();
541+
}
542+
else
543+
{
544+
if (current != null)
545+
{
546+
_cookies.Add(current);
547+
}
548+
549+
current = new Cookie();
550+
var idx = str.IndexOf('=');
551+
if (idx > 0)
552+
{
553+
current.Name = str.Substring(0, idx).Trim();
554+
current.Value = str.Substring(idx + 1).Trim();
555+
}
556+
else
557+
{
558+
current.Name = str.Trim();
559+
current.Value = string.Empty;
560+
}
561+
562+
current.Version = version;
563+
}
564+
}
565+
566+
if (current != null)
567+
{
568+
_cookies.Add(current);
569+
}
570+
}
569571

570572
private void CreateQueryString(string query)
571573
{

src/Unosquare.Labs.EmbedIO/System.Net/HttpListenerResponse.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,7 @@ private void Close(bool force)
611611
{
612612
_disposed = true;
613613

614-
// TODO: Is this fine?
615-
_context.Connection.CloseAsync(force).Wait();
614+
_context.Connection.Close(force);
616615
}
617616
}
618617
}

0 commit comments

Comments
 (0)