From 25cc39e0b5e942858e0a15fd56d29d6db34734a0 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 5 May 2024 14:22:38 -0500 Subject: [PATCH] KeeAgentExt: disable background UI thread on Mono This causes KeePass to lock up just by starting the thread and opening a random dialog on the main thread. To work around, we just go back to the old behavior on Mono from before the background thread was added. Fixes: https://github.com/dlech/KeeAgent/issues/410 --- KeeAgent/KeeAgentExt.cs | 50 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/KeeAgent/KeeAgentExt.cs b/KeeAgent/KeeAgentExt.cs index 35d8d60..0e64ea6 100644 --- a/KeeAgent/KeeAgentExt.cs +++ b/KeeAgent/KeeAgentExt.cs @@ -103,7 +103,10 @@ public override bool Initialize(IPluginHost host) var domainSocketPath = Environment.GetEnvironmentVariable(UnixClient.SshAuthSockName); try { - _uiThread = new KeeAgentUiThread(); + // background UI thread breaks Mono + if (Type.GetType("Mono.Runtime") == null) { + _uiThread = new KeeAgentUiThread(); + } if (Options.AgentMode != AgentMode.Client) { if (isWindows) { // In windows, try to start an agent. If Pageant is running, we will @@ -117,8 +120,13 @@ public override bool Initialize(IPluginHost host) pagent.MessageReceived += PageantAgent_MessageReceived; // IMPORTANT: if you change either of these callbacks, you need // to make sure that they do not block the main event loop. - pagent.FilterKeyListCallback = FilterKeyList; - pagent.ConfirmUserPermissionCallback = ConfirmUserPermissionCallback; + if (Type.GetType("Mono.Runtime") == null) { + pagent.FilterKeyListCallback = FilterKeyList; + pagent.ConfirmUserPermissionCallback = ConfirmUserPermissionCallback; + } else { + pagent.FilterKeyListCallback = FilterKeyListMono; + pagent.ConfirmUserPermissionCallback = Default.ConfirmCallback; + } agent = pagent; if (Options.UseCygwinSocket) { StartCygwinSocket(); @@ -151,8 +159,13 @@ public override bool Initialize(IPluginHost host) unixAgent.MessageReceived += PageantAgent_MessageReceived; // IMPORTANT: if you change either of these callbacks, you need // to make sure that they do not block the main event loop. - unixAgent.FilterKeyListCallback = FilterKeyList; - unixAgent.ConfirmUserPermissionCallback = ConfirmUserPermissionCallback; + if (Type.GetType("Mono.Runtime") == null) { + unixAgent.FilterKeyListCallback = FilterKeyList; + unixAgent.ConfirmUserPermissionCallback = ConfirmUserPermissionCallback; + } else { + unixAgent.FilterKeyListCallback = FilterKeyListMono; + unixAgent.ConfirmUserPermissionCallback = Default.ConfirmCallback; + } agent = unixAgent; if (Options.UnixSocketPath == null) { var autoModeMessage = Options.AgentMode == AgentMode.Auto @@ -1242,7 +1255,6 @@ IEnumerable FilterKeyList(IEnumerable list) } _uiThread.Invoke(() => { - //var zIndex = pluginHost.MainWindow.GetZIndex(); var dialog = new KeyPicker(list); dialog.Shown += (sender, e) => dialog.Activate(); dialog.StartPosition = FormStartPosition.CenterScreen; @@ -1259,5 +1271,31 @@ IEnumerable FilterKeyList(IEnumerable list) return list; } + + // same as above, but without the background UI thread + IEnumerable FilterKeyListMono(IEnumerable list) + { + if (!Options.UserPicksKeyOnRequestIdentities || !list.Any()) { + return list; + } + + // TODO: Using the main thread here will cause a lockup with IOProtocolExt + pluginHost.MainWindow.Invoke((MethodInvoker)delegate { + var dialog = new KeyPicker(list); + dialog.Shown += (sender, e) => dialog.Activate(); + dialog.TopMost = true; + dialog.ShowDialog(pluginHost.MainWindow); + if (dialog.DialogResult == DialogResult.OK) { + list = dialog.SelectedKeys.ToList(); + } + else { + list = Enumerable.Empty(); + } + + pluginHost.MainWindow.SetWindowPosBottom(); + }); + + return list; + } } // class } // namespace