Hi all, I just had a familiar (to me) problem reappear: zombie hooks getting called after program exit, which leads to a crash upon Wine exit. It turns out that the module that created the guilty hook (TOPHOOK.DLL, hMod 0x0287) didn't get cleaned up properly. It does: Call USER.121: SETWINDOWSHOOK(0x0005,0x029f0010) ret=029f:02d4 ds=02af trace:hook:HOOK_SetHook Setting hook 5: 029f0010 0287 00000000 trace:hook:HOOK_SetHook Setting hook 5: ret=0328 [next=0000] Ret USER.121: SETWINDOWSHOOK() retval=0x4b480328 ret=029f:02d4 ds=02af TOPHOOK.DLL gets loaded here: trace:module:CreateProcessA tidy_cmdline: name 'C:\WRK\UTIL\TOPDESK.EXE'[23], cmdline ''[0] trace:module:NE_LoadExeHeader Using fast-load area offset=800 len=32256 trace:module:NE_LoadExeHeader Converting entry table. trace:module:NE_LoadExeHeader entry table: offs 0175, len 0027, entries 6 trace:module:NE_LoadExeHeader first bundle: 0x40a71cf5 trace:module:GetModuleHandle16 (KERNEL) trace:task:TASK_Create module='topdesk' cmdline='' task=025f trace:module:NE_LoadDLLs Loading 'TOPHOOK' trace:module:GetModuleHandle16 (TOPHOOK) trace:module:MODULE_GetLoadOrder Looking for 'TOPHOOK.DLL' (TOPHOOK), found '<nothing>' . . . trace:module:NE_OpenFile opened 'C:\WINDOWS\TOPHOOK.DLL' -> 1414155699 Upon program exit that happens: Call KERNEL.102: DOS3CALL() ret=0277:516a ds=027f AX=4c00 BX=0078 CX=0000 DX=0b7a SI=06e8 DI=06e8 ES=027f EFL=00000202 . . . trace:task:TASK_KillTask Killing task 025f ("topdesk") trace:hook:USER_ModuleUnload (022f) trace:module:NE_FreeModule 022f wep 1 count 1 trace:module:NE_FreeModule 0287 wep 0 count 1 trace:module:NE_FreeModule 00de wep 0 count 3 trace:module:NE_FreeModule 01e6 wep 0 count 3 trace:module:NE_FreeModule 02b6 wep 0 count 1 trace:module:NE_FreeModule 00de wep 0 count 2 trace:module:NE_FreeModule 01c6 wep 0 count 2 trace:module:NE_FreeModule 01e6 wep 0 count 2 trace:task:TASK_Reschedule entered with hCurrentTask 025f by hTask 025f (pid 19659) trace:task:TASK_Reschedule task = 01af, events = 1 trace:task:TASK_Reschedule Switching to task 01af (KERNEL) Ret USER32.270: GetMessageA() retval=00000001 ret=080499e5 fs=008f Call USER32.556: TranslateMessage(40a1fde0) ret=080499bb fs=008f Ret USER32.556: TranslateMessage() retval=00000000 ret=080499bb fs=008f Call USER32.141: DispatchMessageA(40a1fde0) ret=080499c3 fs=008f Ret USER32.141: DispatchMessageA() retval=00000000 ret=080499c3 fs=008f trace:module:MODULE_InitDll (USER32.DLL,PROCESS_DETACH,0x1) - CALL trace:relay:PE_InitDLL CallTo32(entryproc=0x40398bd0,module=40ee0000,type=0,res=0x1) trace:module:MODULE_InitDll (USER32.DLL,PROCESS_DETACH,0x1) - RETURN 1 trace:module:MODULE_InitDll (GDI32.DLL,PROCESS_DETACH,0x1) - CALL trace:relay:PE_InitDLL CallTo32(entryproc=0x40398afc,module=40dc0000,type=0,res=0x1) trace:module:MODULE_InitDll (GDI32.DLL,PROCESS_DETACH,0x1) - RETURN 1 trace:module:MODULE_InitDll (KERNEL32.dll,PROCESS_DETACH,0x1) - CALL trace:relay:PE_InitDLL CallTo32(entryproc=0x40398820,module=40d90000,type=0,res=0x1) trace:module:MODULE_InitDll (KERNEL32.dll,PROCESS_DETACH,0x1) - RETURN 1 trace:module:MODULE_InitDll (ntdll.dll,PROCESS_DETACH,0x1) - CALL trace:module:MODULE_InitDll (ntdll.dll,PROCESS_DETACH,0x1) - RETURN 1 trace:task:TASK_KillTask Killing task 01af trace:hook:HOOK_CallHook Calling hook 0328: 4 00000358 00000000 CallTo16(func=029f:0010,ds=0097,0x0004,0x0358,0x0000,0x0000) ss:sp=0097:ffd0 Unhandled exception: priviledged instruction in 32-bit code (0x40395eee). Loading symbols: /usr/local/src/wine/wine And there we are. (0x0297:0x0010 isn't valid any more) Task 0x025f that gets killed is the program named "topdesk" which referenced the TOPHOOK.DLL. According to above, we do a USER_ModuleUnload of 0x022f (what the hell is this ?) and after that we do a NE_FreeModule of it which causes recursive NE_FreeModule()s of other module, *all* of them with call_wep set to 0 !!! But in NE_FreeModule() we have this code: if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32)) { if (pModule->flags & NE_FFLAGS_LIBMODULE) { MODULE_CallWEP( hModule ); /* Free the objects owned by the DLL module */ TASK_CallTaskSignalProc( USIG16_DLL_UNLOAD, hModule ); PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, 0, hModule ); } else call_wep = FALSE; /* We are freeing a task -> no more WEPs */ } So obviously upon first entry the else call_wep = FALSE; /* We are freeing a task -> no more WEPs */ gets triggered as this is a task. Then the NE_FreeModule() loop further below gets called with call_wep set to FALSE. This however prevents further TASK_CallTaskSignal... and *especially* PROCESS_CallUserSignalProc(...) from being called (which is responsible for hook unloading !!). So all DLLs referenced by a task seem to have their hooks not properly unregistered upon task exit. -> zombie hooks getting called -> crash. I therefore think that calling TASK_CallTaskSignalProc and PROCESS_CallUserSignalProc only within the WEP handling is blatantly wrong. Or at least the hooks should be cleaned up somehow independently from the WEP handling... Comments ? (I'd have loved posting a patch already, but then I'm no expert at all about the whole thing here...) Andreas Mohr