fix: retry OpenClipboard() on Windows

OpenClipboard() can fail transiently when another process holds the
clipboard mutex. Add a retry loop (5 attempts, 5ms delay) so that
Deskflow handles brief contention gracefully instead of immediately
failing.
This commit is contained in:
UberKitten 2026-02-27 07:22:22 -08:00 committed by Chris Rizzitello
parent 7126f31d3f
commit ac8cc42b7a

View file

@ -1,5 +1,6 @@
/* /*
* Deskflow -- mouse and keyboard sharing utility * Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
@ -116,14 +117,26 @@ bool MSWindowsClipboard::open(Time time) const
{ {
LOG_DEBUG("open clipboard"); LOG_DEBUG("open clipboard");
if (!OpenClipboard(m_window)) { // The clipboard is a global mutex on Windows. We aren't always going to
LOG_WARN("failed to open clipboard: %d", GetLastError()); // get the lock on the first try, so try a few times before giving up.
return false; // Based on Chromium's ScopedClipboard::Acquire() retry loop.
static const int kMaxRetries = 5;
static const int kRetryDelayMs = 5;
for (int i = 0; i < kMaxRetries; ++i) {
if (OpenClipboard(m_window)) {
m_time = time;
return true;
} }
m_time = time; if (i < kMaxRetries - 1) {
LOG_DEBUG("failed to open clipboard (attempt %d/%d, error=%d), retrying", i + 1, kMaxRetries, GetLastError());
Sleep(kRetryDelayMs);
}
}
return true; LOG_WARN("failed to open clipboard after %d attempts: %d", kMaxRetries, GetLastError());
return false;
} }
void MSWindowsClipboard::close() const void MSWindowsClipboard::close() const