United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4916767 applets hang on multimon systems after returning from StandBy (Windows XP)
JDK-4916767 : applets hang on multimon systems after returning from StandBy (Windows XP)

Details
Type:
Bug
Submit Date:
2003-09-03
Status:
Resolved
Updated Date:
2004-01-15
Project Name:
JDK
Resolved Date:
2003-09-29
Component:
client-libs
OS:
windows_nt,windows_xp
Sub-Component:
2d
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.2,1.4.2_02,5.0
Fixed Versions:
1.4.2_04 (04)

Related Reports
Backport:
Duplicate:
Duplicate:

Sub Tasks

Description
To reproduce this problem:

- Use an XP system with multimon (for example, a Matrox G550, which is what
the reporting user had and what I used to reproduce the bug with)
- Go to http://go.icq.com
- Log in (you need to create an account if you do not have one already; it's free)
- Move the chat applet window to the second head
- Go to StandBy (one of the shutdown options)
- Restart the machine
- Notice that the applet window is still up, but that it is completely hung;
there are blank or black rectangles in the window that will never go away,
even when resizing the window.  It is simply not responding to events.


                                    

Comments
EVALUATION

This boils down to a CriticalSection usage bug.  The hanging that we see in the applet is caused by our rendering thread coming to a complete halt as it waits for a CriticalSection (surfaceLock) to be released which will never be released.

The problem is that we have already released the CriticalSection ... twice.

In DDrawSurface::GetDC(), we ask a ddraw surface for an HDC object that we can use to render with GDI.  Like all calls in DDrawSurface, we first grab the surfaceLock CriticalSection, to ensure that no other thread messes with the surface while we are using it.  If the call to GetDC on the surface fails, then we release the CriticalSection because the calling code should not call ReleaseDC since the HDC is NULL (and therefore invalid).

This works for most of the cases that call GetDC; all of the functions in Win32Renderer noop when the HDC is NULL and simply return without calling ReleaseDC (thus there is exactly one Enter and one Leave for the surfaceLock CriticalSection).

However, there is code in Win32BlitLoops.cpp that does not behave this convention.  When we are in a multimon situation and require a Blt to the secondary screen, then we call GetDC for the src and destination surfaces
(in this case, the src is a ddraw offscreen surface and the dest is the onscreen window).  But we do not check for failure of GetDC; we simply proceed with the GDI BitBlt() operations and then eventually call ReleaseDC() for both the src and destination.  This means that if we ever fail the call to GetDC and return NULL, we will release the surfaceLock once during the failure of GetDC, and then release it again during the later (incorrect) call to ReleaseDC.  If a CriticalSection is released more than once, the results are unpredictable.  From the MSDN docs: "If a thread calls LeaveCriticalSection when it does not have ownership ... an error occurs that may cause another thread using EnterCriticalSection to wait indefinitely."

The fix is easy: make the code in Win32BlitLoops behave by:
- checking for a NULL HDC for both the src and dst surfaces
- if either are NULL, release the one that is non-NULL, and return from the function (noop; we cannot hope to actually do a Gdi blit here since we did not get the structures necessary for performing the operation).

###@###.### 2003-09-03
                                     
2003-09-03
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_04
generic
tiger

FIXED IN:
1.4.2_04
tiger

INTEGRATED IN:
1.4.2_04
tiger
tiger-b22


                                     
2004-06-14



Hardware and Software, Engineered to Work Together