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().

 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 ();
+         if (err == ERROR_NOT_FOUND)
+           return true;
+         CloseClipboard ();
+         if (err != ERROR_CLIPBOARD_NOT_OPEN)
+           return false;
+       }
       Sleep (1);
     }
   return false;
-- 
2.51.0

Reply via email to