Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Made some fixes to the SSE event stream reader.

- Handle exceptions on the read task better.
- Don't raise onopened if the first read is a failure.
  • Loading branch information...
commit 7f0fd4ddc70e6fe2561a3eb6bfd0a9acf3ee4576 1 parent d26b018
@davidfowl davidfowl authored
View
78 SignalR.Client/Transports/ServerSentEvents/EventSourceStreamReader.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Threading;
+using System.Threading.Tasks;
using SignalR.Client.Infrastructure;
namespace SignalR.Client.Transports.ServerSentEvents
@@ -80,40 +81,72 @@ public void Close()
private void Process()
{
+ Read:
+
if (!Processing)
{
return;
}
var buffer = new byte[4096];
- _stream.ReadAsync(buffer).ContinueWith(task =>
- {
- // When the first get data from the server the trigger the event.
- Interlocked.Exchange(ref _setOpened, () => { }).Invoke();
- if (task.IsFaulted)
+ Task<int> readTask = _stream.ReadAsync(buffer);
+
+ if (readTask.IsCompleted)
+ {
+ try
{
- Close(task.Exception.Unwrap());
- return;
- }
+ // Observe all exceptions
+ readTask.Wait();
- int read = task.Result;
+ int read = readTask.Result;
- if (read > 0)
- {
- // Put chunks in the buffer
- ProcessBuffer(buffer, read);
+ if (TryProcessRead(buffer, read))
+ {
+ goto Read;
+ }
}
-
- if (read == 0)
+ catch (Exception ex)
{
- Close();
- return;
+ Close(ex);
}
+ }
+ else
+ {
+ ReadAsync(readTask, buffer);
+ }
+ }
- // Keep reading the next set of data
- Process();
- });
+ private void ReadAsync(Task<int> readTask, byte[] buffer)
+ {
+ readTask.Catch(ex => Close(ex))
+ .Then(read =>
+ {
+ if (TryProcessRead(buffer, read))
+ {
+ Process();
+ }
+ })
+ .Catch();
+ }
+
+ private bool TryProcessRead(byte[] buffer, int read)
+ {
+ Interlocked.Exchange(ref _setOpened, () => { }).Invoke();
+
+ if (read > 0)
+ {
+ // Put chunks in the buffer
+ ProcessBuffer(buffer, read);
+
+ return true;
+ }
+ else if (read == 0)
+ {
+ Close();
+ }
+
+ return false;
}
private void ProcessBuffer(byte[] buffer, int read)
@@ -152,6 +185,11 @@ private void Close(Exception exception)
Debug.WriteLine("EventSourceReader: Connection Closed");
if (Closed != null)
{
+ if (exception != null)
+ {
+ exception = exception.Unwrap();
+ }
+
Closed(exception);
}
}
View
20 SignalR.Tests/EventSourceStreamReaderFacts.cs
@@ -27,6 +27,26 @@ public void ReadTriggersOpenedOnOpen()
Assert.Equal("somedata", tcs.Task.Result);
}
+ [Fact]
+ public void CloseThrowsSouldntTakeProcessDown()
+ {
+ var memoryStream = MemoryStream("");
+ var eventSource = new EventSourceStreamReader(memoryStream);
+
+ eventSource.Closed = (ex) =>
+ {
+ throw new Exception("Throw on closed");
+ };
+
+ eventSource.Start();
+
+ // Force any finalizers to run so we can see unhandled task errors
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ Thread.Sleep(TimeSpan.FromSeconds(5));
+ }
+
private MemoryStream MemoryStream(string data)
{
return new MemoryStream(Encoding.UTF8.GetBytes(data));
Please sign in to comment.
Something went wrong with that request. Please try again.