JDK-4916767 : applets hang on multimon systems after returning from StandBy (Windows XP)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.2,1.4.2_02,5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_nt,windows_xp
  • CPU: x86
  • Submitted: 2003-09-03
  • Updated: 2004-01-15
  • Resolved: 2003-09-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
1.4.2_04 04Fixed
Related Reports
Duplicate :  
Duplicate :  
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.

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

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