Skip to content

Commit 18f046b

Browse files
Merge pull request #168 from TylerLeonhardt/jsonrpcserver-now-disposable
JsonRpcServer now disposable
2 parents cf67cdf + 4605713 commit 18f046b

File tree

3 files changed

+58
-46
lines changed

3 files changed

+58
-46
lines changed

src/JsonRpc/InputHandler.cs

+49-41
Original file line numberDiff line numberDiff line change
@@ -72,52 +72,59 @@ private void ProcessInputStream()
7272
// content is encoded in UTF-8
7373
while (true)
7474
{
75-
if (_inputThread == null) return;
76-
77-
var buffer = new byte[300];
78-
var current = _input.Read(buffer, 0, MinBuffer);
79-
if (current == 0) return; // no more _input
80-
while (current < MinBuffer ||
81-
buffer[current - 4] != CR || buffer[current - 3] != LF ||
82-
buffer[current - 2] != CR || buffer[current - 1] != LF)
83-
{
84-
var n = _input.Read(buffer, current, 1);
85-
if (n == 0) return; // no more _input, mitigates endless loop here.
86-
current += n;
87-
}
75+
try {
76+
if (_inputThread == null) return;
77+
78+
var buffer = new byte[300];
79+
var current = _input.Read(buffer, 0, MinBuffer);
80+
if (current == 0) return; // no more _input
81+
while (current < MinBuffer ||
82+
buffer[current - 4] != CR || buffer[current - 3] != LF ||
83+
buffer[current - 2] != CR || buffer[current - 1] != LF)
84+
{
85+
var n = _input.Read(buffer, current, 1);
86+
if (n == 0) return; // no more _input, mitigates endless loop here.
87+
current += n;
88+
}
8889

89-
var headersContent = System.Text.Encoding.ASCII.GetString(buffer, 0, current);
90-
var headers = headersContent.Split(HeaderKeys, StringSplitOptions.RemoveEmptyEntries);
91-
long length = 0;
92-
for (var i = 1; i < headers.Length; i += 2)
93-
{
94-
// starting at i = 1 instead of 0 won't throw, if we have uneven headers' length
95-
var header = headers[i - 1];
96-
var value = headers[i].Trim();
97-
if (header.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
90+
var headersContent = System.Text.Encoding.ASCII.GetString(buffer, 0, current);
91+
var headers = headersContent.Split(HeaderKeys, StringSplitOptions.RemoveEmptyEntries);
92+
long length = 0;
93+
for (var i = 1; i < headers.Length; i += 2)
9894
{
99-
length = 0;
100-
long.TryParse(value, out length);
95+
// starting at i = 1 instead of 0 won't throw, if we have uneven headers' length
96+
var header = headers[i - 1];
97+
var value = headers[i].Trim();
98+
if (header.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
99+
{
100+
length = 0;
101+
long.TryParse(value, out length);
102+
}
101103
}
102-
}
103104

104-
if (length == 0 || length >= int.MaxValue)
105-
{
106-
HandleRequest(string.Empty);
107-
}
108-
else
109-
{
110-
var requestBuffer = new byte[length];
111-
var received = 0;
112-
while (received < length)
105+
if (length == 0 || length >= int.MaxValue)
106+
{
107+
HandleRequest(string.Empty);
108+
}
109+
else
113110
{
114-
var n = _input.Read(requestBuffer, received, requestBuffer.Length - received);
115-
if (n == 0) return; // no more _input
116-
received += n;
111+
var requestBuffer = new byte[length];
112+
var received = 0;
113+
while (received < length)
114+
{
115+
var n = _input.Read(requestBuffer, received, requestBuffer.Length - received);
116+
if (n == 0) return; // no more _input
117+
received += n;
118+
}
119+
// TODO sometimes: encoding should be based on the respective header (including the wrong "utf8" value)
120+
var payload = System.Text.Encoding.UTF8.GetString(requestBuffer);
121+
HandleRequest(payload);
117122
}
118-
// TODO sometimes: encoding should be based on the respective header (including the wrong "utf8" value)
119-
var payload = System.Text.Encoding.UTF8.GetString(requestBuffer);
120-
HandleRequest(payload);
123+
}
124+
catch (IOException)
125+
{
126+
_logger.LogError("Input stream has been closed.");
127+
break;
121128
}
122129
}
123130
}
@@ -229,9 +236,10 @@ private void HandleRequest(string request)
229236

230237
public void Dispose()
231238
{
239+
_scheduler.Dispose();
232240
_outputHandler.Dispose();
233241
_inputThread = null;
234-
_scheduler.Dispose();
242+
_input?.Dispose();
235243
}
236244
}
237245
}

src/JsonRpc/OutputHandler.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public OutputHandler(Stream output, ISerializer serializer)
2323
_serializer = serializer;
2424
_queue = new BlockingCollection<object>();
2525
_cancel = new CancellationTokenSource();
26+
_outputIsFinished = new TaskCompletionSource<object>();
2627
_thread = new Thread(ProcessOutputQueue) { IsBackground = true, Name = "ProcessOutputQueue" };
2728
}
2829

@@ -41,7 +42,7 @@ private void ProcessOutputQueue()
4142
var token = _cancel.Token;
4243
try
4344
{
44-
while (true)
45+
while (!token.IsCancellationRequested)
4546
{
4647
if (_queue.TryTake(out var value, Timeout.Infinite, token))
4748
{
@@ -59,20 +60,23 @@ private void ProcessOutputQueue()
5960
{
6061
ms.Write(headerBytes, 0, headerBytes.Length);
6162
ms.Write(contentBytes, 0, contentBytes.Length);
62-
_output.Write(ms.ToArray(), 0, (int)ms.Position);
63+
if(!token.IsCancellationRequested)
64+
{
65+
_output.Write(ms.ToArray(), 0, (int)ms.Position);
66+
}
6367
}
6468
}
6569
}
6670
}
6771
catch (OperationCanceledException ex)
6872
{
6973
if (ex.CancellationToken != token)
70-
_outputIsFinished.SetException(ex);
74+
_outputIsFinished.TrySetException(ex);
7175
// else ignore. Exceptions: OperationCanceledException - The CancellationToken has been canceled.
7276
}
7377
catch (Exception e)
7478
{
75-
_outputIsFinished.SetException(e);
79+
_outputIsFinished.TrySetException(e);
7680
}
7781
}
7882

src/JsonRpc/ProcessScheduler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private void ProcessRequestQueue()
6868
var waitables = new List<Task>();
6969
try
7070
{
71-
while (true)
71+
while (!token.IsCancellationRequested)
7272
{
7373
if (_queue.TryTake(out var item, Timeout.Infinite, token))
7474
{

0 commit comments

Comments
 (0)