CONVERTED DATA
BugTraq+ Release Management Values
COMMIT TO FIX:
1.3.1_11
1.4.2_04
generic
tiger-beta
FIXED IN:
1.3.1_11
1.4.2_04
tiger-beta
INTEGRATED IN:
1.3.1_11
1.4.2_04
tiger-b32
tiger-beta
|
|
|
SUGGESTED FIX
*** /home/bchristi/jano2/bchristi/tiger/webrev/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp- Fri Nov 7 15:26:57 2003
--- awt_Win32GraphicsConfig.cpp Fri Nov 7 15:25:21 2003
*** 79,90 ****
if( TRUE == ::MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW) ) {
bounds = env->NewObject(clazz, mid,
rRW.left, rRW.top,
rRW.right - rRW.left,
rRW.bottom - rRW.top);
if (safe_ExceptionOccurred(env)) {
return 0;
}
}
- }
return bounds;
}
--- 79,98 ----
if( TRUE == ::MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW) ) {
bounds = env->NewObject(clazz, mid,
rRW.left, rRW.top,
rRW.right - rRW.left,
rRW.bottom - rRW.top);
+ }
+ else {
+ // 4910760 - don't return a null bounds, return the bounds of the
+ // primary screen
+ bounds = env->NewObject(clazz, mid,
+ 0, 0,
+ ::GetSystemMetrics(SM_CXSCREEN),
+ ::GetSystemMetrics(SM_CYSCREEN));
+ }
if (safe_ExceptionOccurred(env)) {
return 0;
}
}
return bounds;
}
*** /home/bchristi/jano2/bchristi/tiger/webrev/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp- Fri Nov 7 15:26:58 2003
--- awt_Win32GraphicsEnv.cpp Thu Nov 6 18:32:01 2003
*** 96,106 ****
for (int i = 0; i < awt_numScreens; i++) {
if (areSameMonitors(mon, getMHNDFromScreen(i))) {
return i;
}
}
! return -1;
}
/*
* Class: sun_awt_Win32GraphicsEnvironment
* Method: initDisplay
--- 96,107 ----
for (int i = 0; i < awt_numScreens; i++) {
if (areSameMonitors(mon, getMHNDFromScreen(i))) {
return i;
}
}
! DTRACE_PRINTLN("getScreenFromMHND(): couldn't find screen, return default");
! return AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
}
/*
* Class: sun_awt_Win32GraphicsEnvironment
* Method: initDisplay
###@###.### 2003-11-25
|
|
|
EVALUATION
Reproducible as described.
###@###.### 2003-11-04
Leaving a Java app running, locking the remote machine, disconnecting, and then reconnecting was not a problem with a "normal" app, such as SwingSet or
Java2Demo. The test case, though, boils down to:
while(weHaven'tDiedYet) {
Frame f = new Frame();
f.pack();
f.dispose();
}
So, even after disconnecting, the test will still (try to) create native backing
windows.
The NPE comes from this swatch of code in Window.java:
Rectangle screenBounds = graphicsConfig.getBounds();
Insets screenInsets = getToolkit().getScreenInsets(graphicsConfig);
---> int x = getX() + screenBounds.x + screenInsets.left;
int y = getY() + screenBounds.y + screenInsets.top;
screenBounds is coming up null, and we NPE on the indicated line. Here's where
the null comes from:
Java_sun_awt_Win32GraphicsConfig_getBounds(JNIEnv *env, jobject thisobj,
jint screen) {
...
jobject bounds = NULL;
...
if( TRUE == ::MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen),
&rRW) ) {
bounds = env->NewObject(clazz, mid,
rRW.left, rRW.top,
rRW.right - rRW.left,
rRW.bottom - rRW.top);
...
}
... return bounds;
}
::MonitorBounds fails, presumably because our cached MHND is no longer valid
after we disconnect from the remote session. bounds remains NULL, and is
returned as such.
The customer works around this in their JDK by not using screenBounds if
it's null (see the Work Around). This may work with 1.3.1_09 and/or 1.4.2_02 (I
didn't try), but I've found that with 1.5 it turns ths exception into a crash. ;(
The crash comes when AwtComponent::SetBackgroundColor() tries to use an array
index of -1. Observe:
void AwtComponent::SetBackgroundColor(COLORREF c)
{
int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
if (grayscale != GS_NOTGRAY) {
...
The basic idea is to get from AwtComponent to grayness via:
HWND->MHND->index into our array of devices->grayness of the device at that index.
The HWND->MHND step is done by the win32 function
::MonitorFromWindow()
called from
AwtWin32GraphicsDevice::DeviceIndexForWindow().
The MHND->index step is done by
getScreenFromMHND()
in
awt_Win32GraphicsEnv.cpp.
So, we get the MHND for our HWND, and look through our cached
AwtWin32GraphicsDevices for that MHND:
int getScreenFromMHND(MHND mon) {
DASSERT(mon != NULL);
for (int i = 0; i < awt_numScreens; i++) {
if (areSameMonitors(mon, getMHNDFromScreen(i))) {
return i;
}
}
return -1;
}
HOWEVER
When we disconnect from the remote server, ::MonitorFromWindow() starts
returning MHNDs we've never seen. I assume it does some sort of display change. At any rate, getScreenFromMHND() nevers finds it, and returns -1.
At first I thought that this problem might be addressed by fixing:
4417798 : Need to track add/remove of monitors on display changes
but from my debugging statements it looks like the crash happens before we see
the WM_DISPLAYCHANGE. event.
My fix has two parts:
1) Return the bounds of the primary monitor from Win32GraphicsConfig.getBounds()
instead of null in the case that ::MonitorBounds() fails. This prevents the NPE
in Window.java (and anywhere else that might call GC.getBounds()).
2) Return default idx (usually 0) instead of -1 from getScreenFromMHND()
This keeps things running, though in a bit of a weird state, since without
4417798 our AwtWin32GraphicsDevice array is never updated. But it doesn't NPE
or crash.
###@###.### 2003-11-25
|
|
|
WORK AROUND
As screenBounds is null, here is what customer changed in Window.java to workaround the problem:
The change is in the java.awt.Window class, within the Window(GraphicsConfiguration gc) constructor.
/* offset the initial location with the original of the screen */
Rectangle screenBounds = graphicsConfig.getBounds();
int x = getX() + screenBounds.x;
int y = getY() + screenBounds.y;
setLocation(x, y);
becomes
/* offset the initial location with the original of the screen */
Rectangle screenBounds = graphicsConfig.getBounds();
if (screenBounds != null) {
int x = getX() + screenBounds.x;
int y = getY() + screenBounds.y;
setLocation(x, y);
} else {
setLocation(getX(), getY());
}
###@###.### 2003-11-03
|
|
|
|