aboutsummaryrefslogtreecommitdiffstats
path: root/QtVsTools.Core
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2022-02-16 12:48:25 +0100
committerMiguel Costa <miguel.costa@qt.io>2022-02-18 09:52:12 +0000
commit666e8023fb1c0f6e32c4e8747f784047a8524274 (patch)
treef7c1ae67a81264af3f60c3e8253d80bc67d9203f /QtVsTools.Core
parentab62be90eb00433e7d40f76873b2ccdca7fb0a1e (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.cs22
-rw-r--r--QtVsTools.Core/MsBuildProject.cs5
-rw-r--r--QtVsTools.Core/QMake.cs12
-rw-r--r--QtVsTools.Core/QMakeQuery.cs7
-rw-r--r--QtVsTools.Core/QtModules.cs2
-rw-r--r--QtVsTools.Core/QtProject.cs2
-rw-r--r--QtVsTools.Core/QtVersionManager.cs18
-rw-r--r--QtVsTools.Core/VersionInformation.cs7
-rw-r--r--QtVsTools.Core/WaitDialog.cs6
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();
+ });
}
}
}