[Patch] Fix gethwnd race

Brian Ford ford@vss.fsi.com
Fri May 14 22:50:00 GMT 2004


On Fri, 14 May 2004, Christopher Faylor wrote:

> Well, maybe I didn't do anything, since that is exactly what I did after
> investigating MSDN.  I thought I remembered that this was the case but
> I couldn't see anything in MSDN which supported it.  I suppose I should
> just have trusted Sergey on this one.
>
> So, nevermind on this wonderful enhancement.

Just in case it might still be "interesting", here is a revised no muto
patch with the appropriate fatal error changes.  I think it is pretty
straight forward.  If you still prefer the muto route, please feel free.

2004-05-14  Brian Ford  <ford@vss.fsi.com>

	* window.cc (window_started): Make NO_COPY.
	(Winmain): Make errors api_fatal.
	(gethwnd): Fix initialization race.
	(window_init): New function to initialize window_started.
	* winsup.h (window_init): Prototype it.
	* dcrt0.cc (dll_crt0_1): Call it.

-- 
Brian Ford
Senior Realtime Software Engineer
VITAL - Visual Simulation Systems
FlightSafety International
the best safety device in any aircraft is a well-trained pilot...
-------------- next part --------------
Index: window.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/window.cc,v
retrieving revision 1.30
diff -u -p -r1.30 window.cc
--- window.cc	9 Feb 2004 04:04:24 -0000	1.30
+++ window.cc	14 May 2004 22:35:34 -0000
@@ -1,4 +1,4 @@
-/* window.cc: hidden windows for signals/itimer support
+/* window.cc: hidden window for alarms, itimers, and sockets.
 
    Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
 
@@ -73,7 +73,13 @@ WndProc (HWND hwnd, UINT uMsg, WPARAM wP
     }
 }
 
-static HANDLE window_started;
+static NO_COPY HANDLE window_started;
+
+void
+window_init ()
+{
+    window_started = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+}
 
 static DWORD WINAPI
 Winmain (VOID *)
@@ -96,10 +102,7 @@ Winmain (VOID *)
   wc.lpszClassName = classname;
 
   if (!RegisterClass (&wc))
-    {
-      system_printf ("Cannot register window class, %E");
-      return FALSE;
-    }
+    api_fatal ("Cannot register hidden window class, %E");
 
   /* Create hidden window. */
   ourhwnd = CreateWindow (classname, classname, WS_POPUP, CW_USEDEFAULT,
@@ -107,13 +110,10 @@ Winmain (VOID *)
 			  (HWND) NULL, (HMENU) NULL, user_data->hmodule,
 			  (LPVOID) NULL);
 
-  SetEvent (window_started);
-
   if (!ourhwnd)
-    {
-      system_printf ("Cannot create window");
-      return FALSE;
-    }
+    api_fatal ("Cannot create hidden window, %E");
+
+  SetEvent (window_started);
 
   /* Start the message loop. */
 
@@ -129,14 +129,26 @@ gethwnd ()
   if (ourhwnd != NULL)
     return ourhwnd;
 
-  cygthread *h;
+  static NO_COPY long window_waiters;
+  long waiters = InterlockedIncrement (&window_waiters);
+
+  if (ourhwnd == NULL)
+    {
+      if (waiters == 1)
+	{
+	  cygthread *h = new cygthread (Winmain, NULL, "win");
+	  h->zap_h ();
+	}
+
+      WaitForSingleObject (window_started, INFINITE);
+    }
+
+  HANDLE ws;
+
+  if (InterlockedDecrement (&window_waiters) == 0
+      && (ws = (HANDLE) InterlockedExchange ((long *) &window_started, 0)))
+    CloseHandle (ws);
 
-  window_started = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
-  h = new cygthread (Winmain, NULL, "win");
-  h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
-  WaitForSingleObject (window_started, INFINITE);
-  CloseHandle (window_started);
-  h->zap_h ();
   return ourhwnd;
 }
 
Index: winsup.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v
retrieving revision 1.143
diff -u -p -r1.143 winsup.h
--- winsup.h	3 May 2004 11:53:07 -0000	1.143
+++ winsup.h	14 May 2004 22:35:34 -0000
@@ -218,6 +218,7 @@ void events_terminate (void);
 void __stdcall close_all_files ();
 
 /* Invisible window initialization/termination. */
+void window_init (void);
 HWND __stdcall gethwnd (void);
 /* Check if running in a visible window station. */
 extern bool has_visible_window_station (void);
Index: dcrt0.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v
retrieving revision 1.218
diff -u -p -r1.218 dcrt0.cc
--- dcrt0.cc	12 Mar 2004 03:09:28 -0000	1.218
+++ dcrt0.cc	14 May 2004 22:35:34 -0000
@@ -799,6 +799,9 @@ dll_crt0_1 (char *)
   /* Connect to tty. */
   tty_init ();
 
+  /* Initialize hidden window for itimers/sockets. */
+  window_init ();
+
   if (!__argc)
     {
       char *line = GetCommandLineA ();


More information about the Cygwin-patches mailing list