Hi Takashi,
On 6/12/2026 7:54 PM, Takashi Yano wrote:
SetClipboardData() and GetClipboardData() occasionally fail with
ERROR_CLIPBOARD_NOT_OPEN, even though OpenClipboard() succeeded if
NULL HWND is used. Retry until GetClipboardData() does not return
ERROR_CLIPBOARD_NOT_OPEN.
Addresses: https://cygwin.com/pipermail/cygwin/2026-February/259438.html
Signed-off-by: Takashi Yano <[email protected]>
Reviewed-by: Mark Geisert <[email protected]>
---
v2: Handle ERROR_NOT_FOUND case. Call CloseClipboard() in the loop.
v3: Change the timing of CloseClipboard().
Thanks for catching this ^^^ I was just about to mention it myself...
winsup/cygwin/fhandler/clipboard.cc | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/winsup/cygwin/fhandler/clipboard.cc
b/winsup/cygwin/fhandler/clipboard.cc
index 12691c7c1..1273863f4 100644
--- a/winsup/cygwin/fhandler/clipboard.cc
+++ b/winsup/cygwin/fhandler/clipboard.cc
@@ -25,11 +25,26 @@ details. */
static inline bool
open_clipboard ()
{
- const int max_retry = 10;
+ const int max_retry = 20;
for (int i = 0; i < max_retry; i++)
{
+ /* No appropriate HWND exists here. */
if (OpenClipboard (NULL))
- return true;
+ {
+ /* SetClipboardData() and GetClipboardData() occasionally
+ fail with ERROR_CLIPBOARD_NOT_OPEN, even though
+ OpenClipboard() succeeded if NULL HWND is used.
+ Retry until GetClipboardData() does not return
+ ERROR_CLIPBOARD_NOT_OPEN. */
+ if (GetClipboardData (CF_UNICODETEXT))
+ return true;
+ DWORD err = GetLastError ();
Given the ambiguity of "ERROR_NOT_FOUND" I would add a one-line comment
here saying ERROR_NOT_FOUND means GetClipboardData() couldn't find
CF_UNICODETEXT data, but it would return data if you ask for the correct
format. This latter case means the clipboard is indeed open. (Or some
briefer way of saying this complicated case.)
Hmm. Maybe more than one line for that comment. With that, patch is GTG.
+ if (err == ERROR_NOT_FOUND)
+ return true;
+ CloseClipboard ();
+ if (err != ERROR_CLIPBOARD_NOT_OPEN)
+ return false;
+ }
Sleep (1);
}
return false;
Thanks & Regards,
..mark