From 4945aead964d940975ae3d4321ec63520d556a13 Mon Sep 17 00:00:00 2001 From: Karl Burtram Date: Tue, 10 Oct 2017 16:33:04 -0700 Subject: [PATCH] Increase parsing thread stack size to avoid stack overflow (#486) * Increase parsing thread stack size to avoid stack overflow * Fix extra space * Remove extra spaces --- .../LanguageServices/BindingQueue.cs | 28 +++++++++++++------ .../LanguageServices/LanguageService.cs | 18 ++++++++---- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs index 51c94707..b8584e77 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs @@ -17,6 +17,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// public class BindingQueue : IDisposable where T : IBindingContext, new() { + internal const int QueueThreadStackSize = 5 * 1024 * 1024; + private CancellationTokenSource processQueueCancelToken = new CancellationTokenSource(); private ManualResetEvent itemQueuedEvent = new ManualResetEvent(initialState: false); @@ -264,15 +266,18 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices // execute the binding operation object result = null; CancellationTokenSource cancelToken = new CancellationTokenSource(); - var bindTask = Task.Run(() => + + // run the operation in a separate thread + var bindThread = new Thread(() => { result = queueItem.BindOperation( bindingContext, - cancelToken.Token); - }); + cancelToken.Token); + }, BindingQueue.QueueThreadStackSize); + bindThread.Start(); - // check if the binding tasks completed within the binding timeout - if (bindTask.Wait(bindTimeout)) + // check if the binding tasks completed within the binding timeout + if (bindThread.Join(bindTimeout)) { queueItem.Result = result; } @@ -285,12 +290,17 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { queueItem.Result = queueItem.TimeoutOperation(bindingContext); } - + lockTaken = false; - bindTask.ContinueWith((a) => bindingContext.BindingLock.Set()); - } - } + Task.Run(() => + { + // wait for the operation to complete before releasing the lock + bindThread.Join(); + bindingContext.BindingLock.Set(); + }); + } + } catch (Exception ex) { // catch and log any exceptions raised in the binding calls diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index bc0afe6b..96fe16cd 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -762,13 +762,19 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { if (connInfo == null || !parseInfo.IsConnected) { - // parse current SQL file contents to retrieve a list of errors - ParseResult parseResult = Parser.IncrementalParse( - scriptFile.Contents, - parseInfo.ParseResult, - this.DefaultParseOptions); + // parse on separate thread so stack size can be increased + var parseThread = new Thread(() => + { + // parse current SQL file contents to retrieve a list of errors + ParseResult parseResult = Parser.IncrementalParse( + scriptFile.Contents, + parseInfo.ParseResult, + this.DefaultParseOptions); - parseInfo.ParseResult = parseResult; + parseInfo.ParseResult = parseResult; + }, ConnectedBindingQueue.QueueThreadStackSize); + parseThread.Start(); + parseThread.Join(); } else {