Hallo,
I sent a patch to prevent wine from crashing last friday. It happend, when DRIVER_FindFromHDrvr returned NULL. No I found out, that I had sent that patch before last year. Eric answered
this doesn't seem right to me: either the loading fails and we shouldn't get a valid handle, or it succeeds and we should be able to find it there's must be something wrong elsewhere could you please send a -debugmsg +driver,+module,+winmm to see what happens ?
and like before, I can't reproduce the error after reverting the patch:
the error no longer exists. I guess some registry entry was corrupt and a successfull run corrected it later.
However I see a lot of check after DRIVER_FindFromHDrvr() in other parts of the code...
If one dose "grep -3 DRIVER_FindFromHDrvr wine/dlls/winmm/*", every other usage of DRIVER_FindFromHDrvr is like if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
Why should expecting a NULL return be wrong? It happens, as the the crashes show.
Bye
Why should expecting a NULL return be wrong? It happens, as the the crashes show.
no. the cases are different. The ones you refer to (mainly in driver.c) use a hDrvr passed by the called. So, we have to catch erroneous hDrvr values. The case in lolvldrv.c is different. The hDrvr used is the one returned by the call to OpenDriver in the same function. That's why it shouldn't fail (unless someone closes the driver between the call to OpenDriver and the one to DRIVER_FindFromHDrvr - and yes, winmm functions should be made reentrant, why they are not today) A+
"Eric" == Eric Pouech pouech-eric@wanadoo.fr writes:
>> Why should expecting a NULL return be wrong? It happens, as the the >> crashes show. Eric> no. the cases are different. The ones you refer to (mainly in Eric> driver.c) use a hDrvr passed by the called. So, we have to catch Eric> erroneous hDrvr values. The case in lolvldrv.c is different. The Eric> hDrvr used is the one returned by the call to OpenDriver in the Eric> same function. That's why it shouldn't fail (unless someone closes Eric> the driver between the call to OpenDriver and the one to Eric> DRIVER_FindFromHDrvr - and yes, winmm functions should be made Eric> reentrant, why they are not today) A+
Eric,
we discussed the problem some time ago, and came to no conclusion. You requested a debug log, but I didn't hit that error in the meantime. Now I hit it again.
I changed in winmm/driver.c LPWINE_DRIVER DRIVER_TryOpenDriver32(LPCSTR fn, LPARAM lParam2) { LPWINE_DRIVER lpDrv = NULL; HMODULE hModule = 0; LPSTR ptr; LPCSTR cause = 0;
TRACE("(%s, %08lX);\n", debugstr_a(fn), lParam2);
if ((ptr = strchr(fn, ' ')) != NULL) { *ptr++ = '\0'; while (*ptr == ' ') ptr++; if (*ptr == '\0') ptr = NULL; }
FIXME("BON: lpDrv before HeapAlloc is %p\n",lpDrv); lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER)); FIXME("BON: after HeapAlloc %p\n",lpDrv); if(!HeapValidate(GetProcessHeap(), 0, lpDrv)) { FIXME("BON:HeapValidate failed\n"); }
A +relay,+heap,+winmm,+driver log looks like:
trace:winmm:MMDRV_Install ('wineoss.drv', 'wineoss.drv', mapper=N); trace:driver:OpenDriverA ("wineoss.drv", (null), 0x00000000); 0009:Call kernel32.lstrcpynA(406ef9b8,406efb28 "wineoss.drv",00000080) ret=41285668 0009:Ret kernel32.lstrcpynA() retval=406ef9b8 ret=41285668 trace:driver:DRIVER_TryOpenDriver32 ("wineoss.drv", 00000000); fixme:driver:DRIVER_TryOpenDriver32 BON: HeapAlloc is (nil) 0009:Call kernel32.GetCurrentThreadId() ret=0a908a76 0009:Ret kernel32.GetCurrentThreadId() retval=00000009 ret=0a908a76 fixme:driver:DRIVER_TryOpenDriver32 BON: HeapAlloc got 0x41c401c0 0009:Call kernel32.HeapValidate(403a0000,00000000,41c401c0) ret=4128527e 0009:Call ntdll.RtlValidateHeap(403a0000,00000000,41c401c0) ret=4050a731 warn:heap:HEAP_IsRealArena Heap 0x403a0000: block 0x41c401c0 is not inside heap 0009:Ret ntdll.RtlValidateHeap() retval=00000000 ret=4050a731 0009:Ret kernel32.HeapValidate() retval=00000000 ret=4128527e fixme:driver:DRIVER_TryOpenDriver32 BON:HeapValidate failed
Strange: we don't see the RtlHeapAllocate function. But then I remember that the application (_impact.exe from the Xilinx ISE suite) uses the shsmp library for memory allocation (http://www.microquill.com/smartheap/sh_tspec.htm).
So our HeapAlloc get patched by the Microquill code, but probably HeapValidate dose not get patched and things diverge.
Eric, can we do the memory validation perhaps in some other way then by HeapValidate ?
Bye
Strange: we don't see the RtlHeapAllocate function. But then I remember that the application (_impact.exe from the Xilinx ISE suite) uses the shsmp library for memory allocation (http://www.microquill.com/smartheap/sh_tspec.htm).
So our HeapAlloc get patched by the Microquill code, but probably HeapValidate dose not get patched and things diverge.
Eric, can we do the memory validation perhaps in some other way then by HeapValidate ?
several questions here: - if your theory (about missing HeapValidate func) is right: then I think that this memory manager is rather broken and should be fixed and not Wine - but on the other hand, how could you explain that it did work at some point (ie didn't crash) and did it afterwards ? This doesn't seem too logical to me. Perhaps the smartheap API interception mechanism isn't that stable on Wine. IMO, you should start looking at the interception code and see if it puts something in place for HeapValidate, then we'll see what we could do (one quickie is to use RtlValidateHeap instead of HeapValidate, but that's *really* ugly). A+
"Eric" == Eric Pouech pouech-eric@wanadoo.fr writes:
>> Strange: we don't see the RtlHeapAllocate function. But then I >> remember that the application (_impact.exe from the Xilinx ISE suite) >> uses the shsmp library for memory allocation >> (http://www.microquill.com/smartheap/sh_tspec.htm). >> >> So our HeapAlloc get patched by the Microquill code, but probably >> HeapValidate dose not get patched and things diverge. >> >> Eric, can we do the memory validation perhaps in some other way then >> by HeapValidate ? Eric> several questions here: - if your theory (about missing Eric> HeapValidate func) is right: then I think that this memory manager Eric> is rather broken and should be fixed and not Wine - but on the Eric> other hand, how could you explain that it did work at some point Eric> (ie didn't crash) and did it afterwards ? This doesn't seem too Eric> logical to me. Perhaps the smartheap API interception mechanism Eric> isn't that stable on Wine. IMO, you should start looking at the Eric> interception code and see if it puts something in place for Eric> HeapValidate, then we'll see what we could do (one quickie is to Eric> use RtlValidateHeap instead of HeapValidate, but that's *really* Eric> ugly). A+
Eric> - if your theory (about missing HeapValidate func) is right: Eric> then I think that this memory manager is rather broken and Eric> should be fixed and not Wine
We have to deal with a lot of brokenness...
I will try to get in contact with Microquill. But even if they fix it, it will take some time until there fix propagates into those projects that use this library and then there are all these old programs out in the wild. And I think a some big project use this library..
And HeapValidate is not a much used function. For example in our wine tree only uses winmm/driver.c and winmm/lolvldrv.c use HeapValidate outside the heap handling itself.
An probably any user of the Microquill libray who had problems with HeapValidate circumvented the problem in the meantime...
Eric> - but on the other hand, how could you explain that it did Eric> work at some point (ie didn't crash) and did it afterwards ? Eric> This doesn't seem too logical to me. Perhaps the smartheap Eric> API interception mechanism isn't that stable on Wine.
Well, impact is the end of the tool chain. There were a lot of other problems, so I didn't look at the impact problem. And it only happens with wine running as win95/98. This is probably the reason why Xilinx ISE requests win2k or winxp.
Eric> IMO, you should start looking at the interception code and Eric> see if it puts something in place for HeapValidate, then we'll Eric> see what we could do (one quickie is to use RtlValidateHeap Eric> instead of HeapValidate, but that's *really* ugly).
I tried the other way. Using RtlAllocateHeap also showed the problem. But when I did a GetProcAddres on RtlAllocateHeap, things worked as expected (the trace showed a RtlAllocateHeap and the following Heapvalidate reported success).
Is using GetProcAddress on HeapAllocate an acceptable solution for that problem?
Bye