[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    RE: WIN_CritSection problem
From:       "Francois Boisvert" <francois () macadamian ! com>
Date:       1999-04-29 18:15:18
[Download RAW message or body]

Hi Andreas!

> The problem is that without this patch the window structure remains locked
> during the window proc call.
> As several InstallShield installers do a DispatchMessage16() which calls
> a huge part of code (in fact 10000 relay lines until a wnd crst deadlock),
> this huge code of course tries to use window locking, which fails.
> But the problem with the patch is that it exposes a "raw", i.e. unlocked,
> winproc variable which might get changed again by other threads
> even before the CallWindowProc16() is issued.
>
> So I'm not sure at all if this fix is valid or if I found The Right Thing
> at all.
> But I guess it is valid...
>

Your fix is not valid because the windows lock is always suspended before
any call to a window procedure. Check WINPROC_CallWndProc (in
windows/winproc.c) and CALLBACK_CallWndProc (in misc/callback.c) for further
explications. The problem probably happens a lot earlier in the program
execution and it's very hard to tell where/when.

That's why I've attached a patch that contains a couple of debugging
functions that are able to print out all threads WIN_CritSection activities.
Just apply the patch WinLockDebug.diff and run your test program without
any -debugmsg. Make sure to redirect the output in a file because it can get
really big and you wont be able to see a thing in your shell.

If you find nothing, send me the output file and I'll see what I can do.

Francois


Email : francois@macadamian.com
____________________________________________

Macadamian Technologies Inc.
700, Industrial Avenue
suite 220
Ottawa, ON, K1G 0Y9
http://www.macadamian.com
____________________________________________

["WinLockDebug.diff" (text/plain)]

Index: windows/win.c
===================================================================
RCS file: /home/wine/wine/windows/win.c,v
retrieving revision 1.50
diff -u -w -r1.50 win.c
--- windows/win.c	1999/04/19 14:56:45	1.50
+++ windows/win.c	1999/04/23 13:48:36
@@ -34,6 +34,8 @@
 #include "local.h"
 #include "desktop.h"
 
+#include "debugger.h"
+
 DECLARE_DEBUG_CHANNEL(msg)
 DECLARE_DEBUG_CHANNEL(win)
 
@@ -51,6 +53,92 @@
 
 /* thread safeness */
 static CRITICAL_SECTION WIN_CritSection;
+static DWORD ThreadArray[20];
+static int ThreadMarker = 0;
+typedef struct
+{
+    DWORD bp;
+    DWORD ip;
+}MYFRAME;
+
+#define GET_ESP(res) __asm__( "movl %%esp,%0" : "=r" (res))
+#define GET_EBP(res) __asm__( "movl %%ebp,%0" : "=r" (res))
+
+//#define WIN_DEBUG TRUE
+
+int WIN_GetRecCount()
+{
+    return WIN_CritSection.RecursionCount;
+}
+
+void PrintCaller(int back)
+{
+    DBG_ADDR addr;
+    DWORD mystack;
+    MYFRAME *caller;
+    int i=0;
+    
+    GET_EBP(mystack);
+    caller = (MYFRAME *)mystack;
+    for(;i<back;i++)
+    {
+        caller = (MYFRAME *)caller->bp;
+    }
+
+    
+    addr.seg = 0;
+    addr.off = caller->ip;
+
+    DEBUG_PrintAddress(&addr,32,TRUE);
+    
+}
+
+void CheckThread(DWORD ThreadId)
+{
+    int i = 0;
+    for(;i<ThreadMarker;i++)
+    {
+        if(ThreadId == ThreadArray[i])
+            return;
+    }
+    ThreadArray[ThreadMarker] = ThreadId;
+    ThreadMarker++;
+
+}
+void PrintThreadAction(int Action)
+{
+
+    DWORD ThreadId = GetCurrentThreadId();
+    
+    int i = 0;
+    for(;i<ThreadMarker;i++)
+    {
+        if(ThreadArray[i] == ThreadId)
+            break;
+        printf("--------");
+    }
+    printf(" %lx : ",ThreadId);
+    switch(Action)
+    {
+    case 1: printf("LOCKED   %lx   ",WIN_CritSection.RecursionCount);
+    for(i=0;i<WIN_CritSection.RecursionCount;i++)
+        printf("  ");
+    PrintCaller(3);
+    break;
+    case 2: printf("UNLOCKED   %lx ",WIN_CritSection.RecursionCount);
+    for(i=0;i<WIN_CritSection.RecursionCount;i++)
+        printf("  ");
+    PrintCaller(3);
+    break;
+    case 3: printf("SUSPEND      ");
+    break;
+    case 4: printf("RESTORE      ");
+    break;
+    }
+    
+    printf(" -> CS thread %lx\n",WIN_CritSection.OwningThread);
+
+}
 
 /***********************************************************************
  *           WIN_LockWnds
@@ -59,7 +147,13 @@
  */
 void WIN_LockWnds()
 {
+/*
+     This code will be released in the future
+     info : francois@macadamian.com
+*/
     EnterCriticalSection(&WIN_CritSection);
+    CheckThread(GetCurrentThreadId());
+    PrintThreadAction(1);
 }
 
 /***********************************************************************
@@ -69,7 +163,14 @@
  */
 void WIN_UnlockWnds()
     {
+/*
+     This code will be released in the future
+     info : francois@macadamian.com
+*/
+    CheckThread(GetCurrentThreadId());
+    PrintThreadAction(2);
         LeaveCriticalSection(&WIN_CritSection);
+
 }
 /***********************************************************************
  *           WIN_SuspendWndsLock
@@ -94,8 +195,10 @@
      so the owning thread will be able to leave it */
     WIN_CritSection.RecursionCount = 1;
     /* leave critical section*/
-    WIN_UnlockWnds();
-
+    //WIN_UnlockWnds();
+    CheckThread(GetCurrentThreadId());
+    PrintThreadAction(3);
+    LeaveCriticalSection(&WIN_CritSection);
     return isuspendedLocks;
 }
 
@@ -111,10 +214,13 @@
         return;
     }
     /* restore the lock */
-    WIN_LockWnds();
+    //WIN_LockWnds();
+    EnterCriticalSection(&WIN_CritSection);
     /* set the recursion count of the critical section to the
      value of suspended locks (given by WIN_SuspendWndsLock())*/
     WIN_CritSection.RecursionCount = ipreviousLocks;
+    CheckThread(GetCurrentThreadId());
+    PrintThreadAction(4);
 
 }
 
@@ -313,7 +419,6 @@
 BOOL WIN_UnlinkWindow( HWND hwnd )
 {    
     WND *wndPtr, **ppWnd;
-    BOOL ret = FALSE;
 
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     else if(!wndPtr->parent)
@@ -321,16 +426,11 @@
         WIN_ReleaseWndPtr(wndPtr);
         return FALSE;
     }
-
     ppWnd = &wndPtr->parent->child;
-    while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
-    if (*ppWnd)
-    {
+    while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
         *ppWnd = wndPtr->next;
-        ret = TRUE;
-    }
     WIN_ReleaseWndPtr(wndPtr);
-    return ret;
+    return TRUE;
 }
 
 
@@ -608,6 +708,7 @@
     /* Initialisation of the critical section for thread safeness */
     InitializeCriticalSection(&WIN_CritSection);
     MakeCriticalSectionGlobal(&WIN_CritSection);
+    DEBUG_ReadSymbolTable("wine.sym");
 
     if (!ICONTITLE_Init() ||
 	!WINPOS_CreateInternalPosAtom() ||

=========================================================================


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic