Skip to content

Commit

Permalink
KeeAgentExt: disable background UI thread on Mono
Browse files Browse the repository at this point in the history
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: #410
  • Loading branch information
dlech committed May 5, 2024
1 parent c2d0dc2 commit 25cc39e
Showing 1 changed file with 44 additions and 6 deletions.
50 changes: 44 additions & 6 deletions KeeAgent/KeeAgentExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1242,7 +1255,6 @@ IEnumerable<ISshKey> FilterKeyList(IEnumerable<ISshKey> list)
}

_uiThread.Invoke(() => {
//var zIndex = pluginHost.MainWindow.GetZIndex();
var dialog = new KeyPicker(list);
dialog.Shown += (sender, e) => dialog.Activate();
dialog.StartPosition = FormStartPosition.CenterScreen;
Expand All @@ -1259,5 +1271,31 @@ IEnumerable<ISshKey> FilterKeyList(IEnumerable<ISshKey> list)

return list;
}

// same as above, but without the background UI thread
IEnumerable<ISshKey> FilterKeyListMono(IEnumerable<ISshKey> 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<ISshKey>();
}

pluginHost.MainWindow.SetWindowPosBottom();
});

return list;
}
} // class
} // namespace

0 comments on commit 25cc39e

Please sign in to comment.