Skip to content

Commit 2777795

Browse files
authored
Merge pull request #603 from Flow-Launcher/FixJsonRPCBufferExceed
Add a MemoryStream buffer to ReadStream first
2 parents 7a355d4 + 466b825 commit 2777795

File tree

2 files changed

+68
-14
lines changed

2 files changed

+68
-14
lines changed

Flow.Launcher.Core/Flow.Launcher.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<ItemGroup>
5656
<PackageReference Include="Droplex" Version="1.3.1" />
5757
<PackageReference Include="FSharp.Core" Version="4.7.1" />
58+
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.1.3" />
5859
<PackageReference Include="squirrel.windows" Version="1.5.2" />
5960
</ItemGroup>
6061

Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
using System.Windows.Forms;
1212
using Flow.Launcher.Infrastructure.Logger;
1313
using Flow.Launcher.Plugin;
14+
using ICSharpCode.SharpZipLib.Zip;
1415
using JetBrains.Annotations;
16+
using Microsoft.IO;
1517

1618
namespace Flow.Launcher.Core.Plugin
1719
{
@@ -33,9 +35,11 @@ internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu
3335
protected abstract string ExecuteCallback(JsonRPCRequestModel rpcRequest);
3436
protected abstract string ExecuteContextMenu(Result selectedResult);
3537

38+
private static readonly RecyclableMemoryStreamManager BufferManager = new();
39+
3640
public List<Result> LoadContextMenus(Result selectedResult)
3741
{
38-
string output = ExecuteContextMenu(selectedResult);
42+
var output = ExecuteContextMenu(selectedResult);
3943
try
4044
{
4145
return DeserializedResult(output);
@@ -61,12 +65,23 @@ private async Task<List<Result>> DeserializedResultAsync(Stream output)
6165
{
6266
if (output == Stream.Null) return null;
6367

64-
var queryResponseModel = await
65-
JsonSerializer.DeserializeAsync<JsonRPCQueryResponseModel>(output, options);
68+
try
69+
{
70+
var queryResponseModel =
71+
await JsonSerializer.DeserializeAsync<JsonRPCQueryResponseModel>(output, options);
6672

67-
await output.DisposeAsync();
68-
69-
return ParseResults(queryResponseModel);
73+
return ParseResults(queryResponseModel);
74+
}
75+
catch (JsonException e)
76+
{
77+
Log.Exception(GetType().FullName, "Unexpected Json Input", e);
78+
}
79+
finally
80+
{
81+
await output.DisposeAsync();
82+
}
83+
84+
return null;
7085
}
7186

7287
private List<Result> DeserializedResult(string output)
@@ -81,15 +96,14 @@ private List<Result> DeserializedResult(string output)
8196

8297
private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
8398
{
84-
var results = new List<Result>();
8599
if (queryResponseModel.Result == null) return null;
86100

87101
if (!string.IsNullOrEmpty(queryResponseModel.DebugMessage))
88102
{
89103
context.API.ShowMsg(queryResponseModel.DebugMessage);
90104
}
91105

92-
foreach (JsonRPCResult result in queryResponseModel.Result)
106+
foreach (var result in queryResponseModel.Result)
93107
{
94108
result.Action = c =>
95109
{
@@ -114,7 +128,8 @@ private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
114128
return !result.JsonRPCAction.DontHideAfterAction;
115129
}
116130

117-
var jsonRpcRequestModel = JsonSerializer.Deserialize<JsonRPCRequestModel>(actionResponse, options);
131+
var jsonRpcRequestModel =
132+
JsonSerializer.Deserialize<JsonRPCRequestModel>(actionResponse, options);
118133

119134
if (jsonRpcRequestModel?.Method?.StartsWith("Flow.Launcher.") ?? false)
120135
{
@@ -125,9 +140,12 @@ private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
125140

126141
return !result.JsonRPCAction.DontHideAfterAction;
127142
};
128-
results.Add(result);
129143
}
130144

145+
var results = new List<Result>();
146+
147+
results.AddRange(queryResponseModel.Result);
148+
131149
return results;
132150
}
133151

@@ -217,16 +235,42 @@ protected string Execute(ProcessStartInfo startInfo)
217235

218236
protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, CancellationToken token = default)
219237
{
238+
Process process = null;
239+
bool disposed = false;
220240
try
221241
{
222-
using var process = Process.Start(startInfo);
242+
process = Process.Start(startInfo);
223243
if (process == null)
224244
{
225245
Log.Error("|JsonRPCPlugin.ExecuteAsync|Can't start new process");
226246
return Stream.Null;
227247
}
228248

229-
var result = process.StandardOutput.BaseStream;
249+
await using var source = process.StandardOutput.BaseStream;
250+
251+
var buffer = BufferManager.GetStream();
252+
253+
token.Register(() =>
254+
{
255+
// ReSharper disable once AccessToModifiedClosure
256+
// Manually Check whether disposed
257+
if (!disposed && !process.HasExited)
258+
process.Kill();
259+
});
260+
261+
try
262+
{
263+
// token expire won't instantly trigger the exception,
264+
// manually kill process at before
265+
await source.CopyToAsync(buffer, token);
266+
}
267+
catch (OperationCanceledException)
268+
{
269+
await buffer.DisposeAsync();
270+
return Stream.Null;
271+
}
272+
273+
buffer.Seek(0, SeekOrigin.Begin);
230274

231275
token.ThrowIfCancellationRequested();
232276

@@ -245,7 +289,7 @@ protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, Cancellati
245289
return Stream.Null;
246290
}
247291

248-
return result;
292+
return buffer;
249293
}
250294
catch (Exception e)
251295
{
@@ -254,15 +298,24 @@ protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, Cancellati
254298
e);
255299
return Stream.Null;
256300
}
301+
finally
302+
{
303+
process?.Dispose();
304+
disposed = true;
305+
}
257306
}
258307

259308
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
260309
{
261-
var output = await ExecuteQueryAsync(query, token);
262310
try
263311
{
312+
var output = await ExecuteQueryAsync(query, token);
264313
return await DeserializedResultAsync(output);
265314
}
315+
catch (OperationCanceledException)
316+
{
317+
return null;
318+
}
266319
catch (Exception e)
267320
{
268321
Log.Exception($"|JsonRPCPlugin.Query|Exception when query <{query}>", e);

0 commit comments

Comments
 (0)