diff options
author | Miguel Costa <miguel.costa@qt.io> | 2022-02-16 12:48:25 +0100 |
---|---|---|
committer | Miguel Costa <miguel.costa@qt.io> | 2022-02-18 09:52:12 +0000 |
commit | 666e8023fb1c0f6e32c4e8747f784047a8524274 (patch) | |
tree | f7c1ae67a81264af3f60c3e8253d80bc67d9203f /QtVsTools.Core | |
parent | ab62be90eb00433e7d40f76873b2ccdca7fb0a1e (diff) |
Avoid potential deadlocks
Multi-threaded access to objects bound to the UI thread can potentially
lead to deadlocks. All functions that participate in a call chain
resulting in the use of objects bound to the UI thread will now call
ThreadHelper.ThrowIfNotOnUIThread(). Where applicable, multi-threaded
functions have been rewritten to ensure that UI-bound objects are only
accessed from the UI thread.
Change-Id: I555bd93c44ae568a9202ca6624b043994d18510a
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
Diffstat (limited to 'QtVsTools.Core')
-rw-r--r-- | QtVsTools.Core/MainWinWrapper.cs | 22 | ||||
-rw-r--r-- | QtVsTools.Core/MsBuildProject.cs | 5 | ||||
-rw-r--r-- | QtVsTools.Core/QMake.cs | 12 | ||||
-rw-r--r-- | QtVsTools.Core/QMakeQuery.cs | 7 | ||||
-rw-r--r-- | QtVsTools.Core/QtModules.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Core/QtProject.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Core/QtVersionManager.cs | 18 | ||||
-rw-r--r-- | QtVsTools.Core/VersionInformation.cs | 7 | ||||
-rw-r--r-- | QtVsTools.Core/WaitDialog.cs | 6 |
9 files changed, 25 insertions, 56 deletions
diff --git a/QtVsTools.Core/MainWinWrapper.cs b/QtVsTools.Core/MainWinWrapper.cs index 2880bd06..42505320 100644 --- a/QtVsTools.Core/MainWinWrapper.cs +++ b/QtVsTools.Core/MainWinWrapper.cs @@ -28,32 +28,18 @@ using System; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; namespace QtVsTools.Core { public class MainWinWrapper : IWin32Window { - private readonly EnvDTE.DTE dteObject; + public IntPtr Handle { get; } public MainWinWrapper(EnvDTE.DTE dte) { - dteObject = dte; - } - - public IntPtr Handle - { - get - { - Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); - - if (dteObject != null) -#if VS2022 - return dteObject.MainWindow.HWnd; -#else - return new IntPtr(dteObject.MainWindow.HWnd); -#endif - return new IntPtr(0); - } + ThreadHelper.ThrowIfNotOnUIThread(); + Handle = new IntPtr((long)dte.MainWindow.HWnd); } } } diff --git a/QtVsTools.Core/MsBuildProject.cs b/QtVsTools.Core/MsBuildProject.cs index 01105838..edba45e5 100644 --- a/QtVsTools.Core/MsBuildProject.cs +++ b/QtVsTools.Core/MsBuildProject.cs @@ -910,9 +910,6 @@ namespace QtVsTools.Core var projPath = this[Files.Project].filePath; bool error = false; - - ThreadHelper.ThrowIfNotOnUIThread(); - using (var evaluator = new MSBuildEvaluator(this[Files.Project])) { foreach (var row in query) { @@ -1202,8 +1199,6 @@ namespace QtVsTools.Core //remove .moc.cbt CustomBuild items cbtToRemove.ForEach(x => x.Remove()); - ThreadHelper.ThrowIfNotOnUIThread(); - //convert moc custom build steps var mocCustomBuilds = GetCustomBuilds(QtMoc.ToolExecName); if (!SetCommandLines(qtMsBuild, configurations, mocCustomBuilds, diff --git a/QtVsTools.Core/QMake.cs b/QtVsTools.Core/QMake.cs index 910c8063..362ee1e5 100644 --- a/QtVsTools.Core/QMake.cs +++ b/QtVsTools.Core/QMake.cs @@ -142,9 +142,6 @@ namespace QtVsTools.Core { StartInfo = qmakeStartInfo, }; - - ThreadHelper.ThrowIfNotOnUIThread(); - qmakeProc.OutputDataReceived += (sender, ev) => OutMsg(ev.Data); qmakeProc.ErrorDataReceived += (sender, ev) => ErrMsg(ev.Data); @@ -153,37 +150,30 @@ namespace QtVsTools.Core protected virtual void OutMsg(string msg) { - ThreadHelper.ThrowIfNotOnUIThread(); if (Dte != null && !string.IsNullOrEmpty(msg)) Messages.Print(msg); } protected virtual void ErrMsg(string msg) { - ThreadHelper.ThrowIfNotOnUIThread(); if (Dte != null && !string.IsNullOrEmpty(msg)) Messages.Print(msg); } protected virtual void InfoMsg(string msg) { - ThreadHelper.ThrowIfNotOnUIThread(); if (Dte != null && !string.IsNullOrEmpty(msg)) Messages.Print(msg); } protected virtual void InfoStart(Process qmakeProc) { - ThreadHelper.ThrowIfNotOnUIThread(); - InfoMsg(string.Format("--- qmake({0}): started {1}", qmakeProc.Id, qmakeProc.StartInfo.FileName)); } protected virtual void InfoExit(Process qmakeProc) { - ThreadHelper.ThrowIfNotOnUIThread(); - InfoMsg(string.Format("--- qmake({0}): exit code {1} ({2:0.##} msecs)\r\n", qmakeProc.Id, qmakeProc.ExitCode, (qmakeProc.ExitTime - qmakeProc.StartTime).TotalMilliseconds)); @@ -244,8 +234,6 @@ namespace QtVsTools.Core protected override void InfoStart(Process qmakeProc) { - ThreadHelper.ThrowIfNotOnUIThread(); - base.InfoStart(qmakeProc); InfoMsg("--- qmake: Working Directory: " + qmakeProc.StartInfo.WorkingDirectory); InfoMsg("--- qmake: Arguments: " + qmakeProc.StartInfo.Arguments); diff --git a/QtVsTools.Core/QMakeQuery.cs b/QtVsTools.Core/QMakeQuery.cs index 5d942839..a1944328 100644 --- a/QtVsTools.Core/QMakeQuery.cs +++ b/QtVsTools.Core/QMakeQuery.cs @@ -50,19 +50,17 @@ namespace QtVsTools.Core protected override void InfoStart(Process qmakeProc) { - ThreadHelper.ThrowIfNotOnUIThread(); - base.InfoStart(qmakeProc); InfoMsg("--- qmake: Querying persistent properties"); } public Dictionary<string, string> QueryAllValues() { + ThreadHelper.ThrowIfNotOnUIThread(); + stdOutput = new StringBuilder(); Query = " "; - ThreadHelper.ThrowIfNotOnUIThread(); - if (Run() == 0 && stdOutput.Length > 0) { return PropertyParser .Parse(stdOutput.ToString()) @@ -93,6 +91,7 @@ namespace QtVsTools.Core get { ThreadHelper.ThrowIfNotOnUIThread(); + return _Properties ?? (_Properties = QueryAllValues()); } } diff --git a/QtVsTools.Core/QtModules.cs b/QtVsTools.Core/QtModules.cs index 4b4bd8c4..547aaa88 100644 --- a/QtVsTools.Core/QtModules.cs +++ b/QtVsTools.Core/QtModules.cs @@ -78,8 +78,6 @@ namespace QtVsTools.Core if (xml == null) return; - Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); - foreach (var xModule in xml.Elements("QtVsTools").Elements("Module")) { int id = (int)xModule.Attribute("Id"); QtModule module = new QtModule(id); diff --git a/QtVsTools.Core/QtProject.cs b/QtVsTools.Core/QtProject.cs index 51e649c1..2fd09a9b 100644 --- a/QtVsTools.Core/QtProject.cs +++ b/QtVsTools.Core/QtProject.cs @@ -2776,6 +2776,8 @@ namespace QtVsTools.Core public bool PromptChangeQtVersion(string oldVersion, string newVersion) { + ThreadHelper.ThrowIfNotOnUIThread(); + var versionManager = QtVersionManager.The(); var viOld = versionManager.GetVersionInfo(oldVersion); var viNew = versionManager.GetVersionInfo(newVersion); diff --git a/QtVsTools.Core/QtVersionManager.cs b/QtVsTools.Core/QtVersionManager.cs index 4b813c23..7700480e 100644 --- a/QtVsTools.Core/QtVersionManager.cs +++ b/QtVsTools.Core/QtVersionManager.cs @@ -278,6 +278,8 @@ namespace QtVsTools.Core public bool SaveVersion(string versionName, string path, bool checkPath = true) { + ThreadHelper.ThrowIfNotOnUIThread(); + var verName = versionName?.Trim().Replace(@"\", "_"); if (string.IsNullOrEmpty(verName)) return false; @@ -298,8 +300,6 @@ namespace QtVsTools.Core } } - ThreadHelper.ThrowIfNotOnUIThread(); - string rootKeyPath = "SOFTWARE\\" + Resources.registryRootPath; string versionKeyPath = strVersionKey + "\\" + verName; using (var key = Registry.CurrentUser.CreateSubKey(rootKeyPath)) { @@ -323,14 +323,13 @@ namespace QtVsTools.Core public void RemoveVersion(string versionName) { + ThreadHelper.ThrowIfNotOnUIThread(); + var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + regVersionPath, true); if (key == null) return; key.DeleteSubKey(versionName); key.Close(); - - ThreadHelper.ThrowIfNotOnUIThread(); - RefreshVersionNames(); } @@ -370,9 +369,6 @@ namespace QtVsTools.Core } return true; } - - ThreadHelper.ThrowIfNotOnUIThread(); - var key = "Qt5Version " + platform; if (!project.Globals.get_VariableExists(key) || project.Globals[key].ToString() != version) project.Globals[key] = version; @@ -488,6 +484,8 @@ namespace QtVsTools.Core public string GetDefaultVersion(RegistryKey root) { + ThreadHelper.ThrowIfNotOnUIThread(); + string defaultVersion = null; try { var key = root.OpenSubKey("SOFTWARE\\" + regVersionPath, false); @@ -536,11 +534,11 @@ namespace QtVsTools.Core private void MergeVersions() { + ThreadHelper.ThrowIfNotOnUIThread(); + var hkcuVersions = GetVersions(); var hklmVersions = GetVersions(Registry.LocalMachine); - ThreadHelper.ThrowIfNotOnUIThread(); - var hkcuInstDirs = new string[hkcuVersions.Length]; for (var i = 0; i < hkcuVersions.Length; ++i) hkcuInstDirs[i] = GetInstallPath(hkcuVersions[i]); diff --git a/QtVsTools.Core/VersionInformation.cs b/QtVsTools.Core/VersionInformation.cs index e5d98519..8c0bb195 100644 --- a/QtVsTools.Core/VersionInformation.cs +++ b/QtVsTools.Core/VersionInformation.cs @@ -94,9 +94,10 @@ namespace QtVsTools.Core private VersionInformation(string qtDirIn) { + ThreadHelper.ThrowIfNotOnUIThread(); + qtDir = qtDirIn; - ThreadHelper.ThrowIfNotOnUIThread(); try { var qmakeQuery = new QMakeQuery(this); SetupPlatformSpecificData(qmakeQuery); @@ -287,10 +288,10 @@ namespace QtVsTools.Core public bool isWinRT() { + ThreadHelper.ThrowIfNotOnUIThread(); + var qmakeQuery = new QMakeQuery(this); string qmakeXSpec; - - ThreadHelper.ThrowIfNotOnUIThread(); try { qmakeXSpec = qmakeQuery["QMAKE_XSPEC"]; } catch { diff --git a/QtVsTools.Core/WaitDialog.cs b/QtVsTools.Core/WaitDialog.cs index cedc078c..38f68d8e 100644 --- a/QtVsTools.Core/WaitDialog.cs +++ b/QtVsTools.Core/WaitDialog.cs @@ -181,8 +181,10 @@ namespace QtVsTools.Core void IDisposable.Dispose() { - ThreadHelper.ThrowIfNotOnUIThread(); - Stop(); + ThreadHelper.JoinableTaskFactory.Run(async () => { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + Stop(); + }); } } } |