Hi.

Attached patch fixes a problem with Beetle Crazy Cup's VideoSetup.exe, which 
hangs at exit because some code tries to free ddraw surface on which a 
refcount underflow happened earlier in the execution.

Executing it with winedbg shows that the first call causing the underflow is 
triggered from game's binary:
Stopped on breakpoint 3 at 0x7ed494fc ddraw1_Release+0x2c 
[/home/vincent/git/wine/dlls/ddraw/ddraw.c:476] in ddraw
476         ULONG ref = InterlockedDecrement(&ddraw->ref1);
Wine-dbg>print ddraw->ref1
0
Wine-dbg>bt
Backtrace:
=>0 0x7ed494fc ddraw1_Release+0x2c(iface=0x129e10) 
[/home/vincent/git/wine/dlls/ddraw/ddraw.c:476] in ddraw (0x0033fd24)
  1 0x00401d2c in videosetup (+0x1d2b) (0x0033fd5c)
  2 0x0040342b in videosetup (+0x342a) (0x0033fd84)
  3 0x004034f5 in videosetup (+0x34f4) (0x0033fda0)
  4 0x00402f65 in videosetup (+0x2f64) (0x0033fe04)
  5 0x00404a4e in videosetup (+0x4a4d) (0x0033fe90)
  6 0x7b8565bc call_process_entry+0xb() in kernel32 (0x0033fea8)
  7 0x7b8565bc call_process_entry+0xb() in kernel32 (0x0033fee8)
  8 0x7b858a9b start_process+0x5a(peb=0x536430) 
[/home/vincent/git/wine/dlls/kernel32/process.c:994] in kernel32 (0x0033fef8)
  9 0x7bc715f0 call_thread_func+0xb() in ntdll (0x0033ffc8)
  10 0x7bc717c0 call_thread_entry_point+0x6f(entry=0x7b858a40, arg=0x7ffdf000) 
[/home/vincent/git/wine/dlls/ntdll/signal_i386.c:2473] in ntdll (0x0033ffe8)
  11 0x7bc4cefa start_process+0x29(kernel_start=0x7b858a40) 
[/home/vincent/git/wine/dlls/ntdll/loader.c:2610] in ntdll (0x00000000)

Points on which I would like opinions:
- getting rid of the magic number
- need to check after InterlockedDecrement (in doubt I did, but the code is
  much less readable this way)
- couldn't it actually hide a refcount problem in wine ?
- if not, then would it be good to extend to other refcounts aswell or include
  in [a local wrapper for] InterlockedDecrement ?

Regards,
---
 dlls/ddraw/ddraw.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index f3ebade..39738d5 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -475,7 +475,11 @@ static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
     ULONG ref = InterlockedDecrement(&ddraw->ref1);
 
-    TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
+    if (ref == 4294967295U) {
+        InterlockedIncrement(&ddraw->ref1);
+        WARN("%p NOT decreasing refcount.\n", ddraw);
+    } else
+        TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
 
     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
         ddraw_destroy(ddraw);


Reply via email to