diff options
author | Kenneth Pouncey <kjpou@pt.lu> | 2018-11-09 15:14:22 +0300 |
---|---|---|
committer | Ludovic Henry <luhenry@microsoft.com> | 2018-11-09 15:14:22 +0300 |
commit | 2bdadca909ca3c7185dd21fb84180c571564dbc5 (patch) | |
tree | 919eb8aaa973c871b7b34ef528281e239e627e21 | |
parent | da2646c36617cdddb61d898da0cc751b2b3d95df (diff) |
Clean up leaks in the WasmHttpMessageHandler. (#11616)
- Most of the leaks present themselves during a Cancel of a streaming request.
-rw-r--r-- | sdks/wasm/WasmHttpMessageHandler.cs | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/sdks/wasm/WasmHttpMessageHandler.cs b/sdks/wasm/WasmHttpMessageHandler.cs index 5aa8b1d47e0..89e0bff577f 100644 --- a/sdks/wasm/WasmHttpMessageHandler.cs +++ b/sdks/wasm/WasmHttpMessageHandler.cs @@ -129,18 +129,23 @@ namespace WebAssembly.Net.Http.HttpClient } JSObject abortController = null; + JSObject signal = null; + WasmHttpReadStream wasmHttpReadStream = null; + CancellationTokenRegistration abortRegistration = default(CancellationTokenRegistration); if (cancellationToken.CanBeCanceled) { abortController = (JSObject)global.Invoke("__mono_wasm_abortcontroller_hook__"); - var signal = abortController.GetObjectProperty("signal"); + signal = (JSObject)abortController.GetObjectProperty("signal"); requestObject.SetObjectProperty("signal", signal); abortRegistration = cancellationToken.Register(() => { if (abortController.JSHandle != -1) { abortController.Invoke("abort"); + abortController?.Dispose(); } + wasmHttpReadStream?.Dispose(); }); } @@ -168,7 +173,7 @@ namespace WebAssembly.Net.Http.HttpClient HttpResponseMessage httpresponse = new HttpResponseMessage((HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), status.Status.ToString())); httpresponse.Content = StreamingSupported && StreamingEnabled - ? new StreamContent(new WasmHttpReadStream(status)) + ? new StreamContent(wasmHttpReadStream = new WasmHttpReadStream(status)) : (HttpContent)new WasmHttpContent(status); // Fill the response headers @@ -196,6 +201,13 @@ namespace WebAssembly.Net.Http.HttpClient } tcs.SetResult(httpresponse); + + // Do not remove the following line of code. The httpresponse is used in the lambda above when parsing the Headers. + // if a local is captured (used) by a lambda it becomes heap memory as we translate them into fields on an object. + // If we do not null the field out it will not be GC'd + httpresponse = null; + + signal?.Dispose(); } catch (Exception exception) { |