United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4908942 JAVA program hangs with XInitThreads call with JDK1.4, but works with JDK1.3.1
JDK-4908942 : JAVA program hangs with XInitThreads call with JDK1.4, but works with JDK1.3.1

Details
Type:
Bug
Submit Date:
2003-08-19
Status:
Closed
Updated Date:
2014-02-14
Project Name:
JDK
Resolved Date:
2004-03-13
Component:
client-libs
OS:
solaris_8,linux
Sub-Component:
java.awt
CPU:
x86,sparc
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.4.2
Fixed Versions:
1.4.2_05 (05)

Related Reports
Backport:
Relates:
Relates:

Sub Tasks

Description
Name: pa48320			Date: 08/19/2003


==================================================================================
                            List of Files
==================================================================================


- readme.txt
- jnitest.c
- Test.java
- TestDialog.java
- ENV
- build_NOUIHANG
- build_UIHANG
- jnitest.sh


==================================================================================
                      FILE : README
==================================================================================


Environment settings to build and run the test case:
---------------------------------------------------

- Edit and set the JAVA_HOME, MOTIF_HOME in the file ENV
- Set the variable  JAVA_HOME to where JDK 1.4.2 is installed
- Set the varibale XWIN_HOME to where X11 library is present
  for ex: /usr/X11R6
- Set the DISPLAY to where X-server is running on Linux platform

How to build the testcase:
-------------------------

- Source the environment file ENV
- run shell script build_UIHANG.sh to create a test case
  to reproduce the problem
- run shell script build_NOUIHANG.sh, to create a test case
  which does not reproduce problem

How to reprouce the problem:
---------------------------

- Build the testcase using build_UIHANG.sh script
- The run the testcase using following steps

How to run the testcase:
-------------------------

- Source the environment file ENV
- run shell script jnitest.sh to run the testcase
- Click Ok , if JAVA  UI comes up fine then
  problem does not reproduce, if JAVA UI comes
  up blank, and program hangs then problem reproduces
- Click Exit to finish

=================================================================================
                   FILE : ENV
=================================================================================

A) File ENV:
-----------

JAVA_HOME=/usr/local/java/j2sdk1.4.1_02; export JAVA_HOME
XWIN_HOME=/usr/X11R6; export XWIN_HOME
RMF="/bin/rm -f"; export RMF

LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/i386/server:${JAVA_HOME}/jre/lib/i386/native_threads:${JAVA_HOME}/jre/lib/i386; export LD_LIBRARY_PATH

CLASSPATH=.:$CLASSPATH; export CLASSPATH


=================================================================================
                  FILE : build_UIHANG.sh
=================================================================================

#! /bin/sh

if [ "x$JAVA_HOME" = 'x' ]
then
echo "JAVA_HOME is not set, please source the file ENV....."
exit 1
fi

if [ -r $JAVA_HOME ]; then
  echo ""
else
  echo "Error: Cannot read JAVA_HOME $JAVA_HOME exiting..."
  exit 1
fi

if [ "x$XWIN_HOME" = 'x' ]
then
echo "XWIN_HOME is not set, please source the file ENV....."
exit 1
fi

if [ -r $XWIN_HOME ]; then
  echo ""
else
  echo "Error: Cannot read XWIN_HOME $MOTIF_HOME exiting..."
  exit 1
fi


/bin/rm -f jnitest.o
/bin/rm -f jnitest
/bin/rm -f Test.class
/bin/rm -f TestDialog.class

/usr/bin/gcc -c jnitest.c -DUIHANG -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -I${XWIN_HOME}/include -I${XWIN_HOME}/include/X11

/usr/bin/gcc -o jnitest jnitest.o -L${XWIN_HOME}/lib  -lX11 -L${JAVA_HOME}/jre/lib/i386 -L${JAVA_HOME}/jre/lib/i386/server -L${JAVA_HOME}/jre/lib/i386/native_threads -ljvm -lhpi

${JAVA_HOME}/bin/javac Test.java

${JAVA_HOME}/bin/javac TestDialog.java


=================================================================================
                  FILE : build_NOUIHANG.sh
=================================================================================

#! /bin/sh

if [ "x$JAVA_HOME" = 'x' ]
then
echo "JAVA_HOME is not set, please source the file ENV....."
exit 1
fi

if [ -r $JAVA_HOME ]; then
  echo ""
else
  echo "Error: Cannot read JAVA_HOME $JAVA_HOME exiting..."
  exit 1
fi

if [ "x$XWIN_HOME" = 'x' ]
then
echo "XWIN_HOME is not set, please source the file ENV....."
exit 1
fi

if [ -r $XWIN_HOME ]; then
  echo ""
else
  echo "Error: Cannot read XWIN_HOME $MOTIF_HOME exiting..."
  exit 1
fi


/bin/rm -f jnitest.o
/bin/rm -f jnitest
/bin/rm -f Test.class
/bin/rm -f TestDialog.class

/usr/bin/gcc -c jnitest.c -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -I${XWIN_HOME}/include -I${XWIN_HOME}/include/X11

/usr/bin/gcc -o jnitest jnitest.o -L${XWIN_HOME}/lib  -lX11 -L${JAVA_HOME}/jre/lib/i386 -L${JAVA_HOME}/jre/lib/i386/server -L${JAVA_HOME}/jre/lib/i386/native_threads -ljvm -lhpi

${JAVA_HOME}/bin/javac Test.java

${JAVA_HOME}/bin/javac TestDialog.java


=================================================================================
                  FILE : jnitest.sh
=================================================================================

#! /bin/sh

. ./ENV

./jnitest


===================================================================================
                  FILE: jnitest.c (Test case Source code)
===================================================================================

#include <jni.h>

int main()
 {
	 JavaVMOption options[2];
	 JNIEnv *env;
	 JavaVM *jvm;
	 JavaVMInitArgs vm_args;
	 long status;
	 jclass cls;
	 jmethodID mid;
	 jint square;
	 jboolean not;

	 options[0].optionString = "-Djava.class.path=.";
   options[1].optionString = "-Xmx256M";
	 memset(&vm_args, 0, sizeof(vm_args));
	 vm_args.version = JNI_VERSION_1_2;

	 vm_args.nOptions = 2;
	 vm_args.options = options;

#ifdef UIHANG
	XInitThreads();
#endif /* UIHANG */

	 status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
   printf("Starting...");

	 if (status != JNI_ERR)
	 {
     printf("Starting...1");
		 cls = (*env)->FindClass(env, "Test");
		 if(cls !=0)
		 {
			 //mid = (*env)->GetStaticMethodID(env, cls, "main", "(I)I");
       mid = (*env)->GetStaticMethodID(env, cls, "main", "(I)V");
       printf("MID IS %d",mid);
			 if(mid !=0)
			 {
				 square = (*env)->CallStaticIntMethod(env, cls, mid, 5);
				 printf("Result of intMethod: %d\n", square);
			 }

			 mid = (*env)->GetStaticMethodID(env, cls, "main", "(Z)Z");
			 if(mid !=0)
			 {
				not = (*env)->CallStaticBooleanMethod(env, cls, mid, 1);
				printf("Result of booleanMethod: %d\n", not);
			 }
	 	 }

	 	(*jvm)->DestroyJavaVM(jvm);
	 	return 0;
	 }
	 else
     printf("Java Error");
	 return -1;
 }

===================================================================================
                  FILE: Test.java (Test case Source code)
===================================================================================

import  javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Test extends JFrame implements ActionListener{


public Test(){
	setSize(300,300);
	JLabel l = new JLabel();
	JButton b = new JButton("Ok");
	JButton c = new JButton("Exit");
	b.addActionListener(this);
	getContentPane().setLayout(new GridLayout(3,1));
	getContentPane().add(l);
	l.setText("Click OK to enter data, Exit to finish");
	getContentPane().add(b);
	c.addActionListener(this);
	getContentPane().add(c);
	setVisible(true);

}

	public void actionPerformed(ActionEvent e){
                if (e.getActionCommand().equals("Ok"))
                {
		     TestDialog t = new TestDialog(this);
                }
                else if(e.getActionCommand().equals("Exit"))
                {
		     System.exit(0);
                }

	}
	public static void main(int i){
		new Test();

	}
}



===================================================================================
                  FILE: TestDialog.java (Test case Source code)
===================================================================================


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TestDialog extends JDialog implements KeyListener{

	public void keyPressed(KeyEvent k){
	System.out.println("Key Pressed");
	}
	public void keyReleased(KeyEvent k){
	System.out.println("Key Released");
	}
	public void keyTyped(KeyEvent k){
	System.out.println("Key Typed");
	}
 	public TestDialog(JFrame par){
		super(par,"TestDialog",true);
		addKeyListener(this);
		JPanel p = new JPanel();
		p.setLayout(new GridLayout(4,1));
		JTextField t1 = new JTextField();
		JTextField t2 = new JTextField();
		JTextField t3 = new JTextField();
		JButton b = new JButton("Ok");
		p.add(t1);
		p.add(t2);
		p.add(t3);
		p.add(b);
		getContentPane().add(p);
		setSize(300,300);
		setLocation(200,200);
		setVisible(true);

	}
}
(Incident Review ID: 199089) 
======================================================================

                                    

Comments
EVALUATION

nt, XPointer data) {
    FocusOutInfo_t * prev = (FocusOutInfo_t *)data;
    JNIEnv	*env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (event->type == FocusIn
        && event->xfocus.serial == prev->eventOut->xfocus.serial
        && event->xfocus.mode == prev->eventOut->xfocus.mode) {        
        Widget w = NULL;
        jobject wpeer = NULL;
        jboolean exc;
        w = XtWindowToWidget(awt_display, event->xfocus.window);
        if (w != NULL) {
            if (!isTopLevelPartWidget(w))
            {
                if (prev->inChild != None &&
                    prev->childComp == NULL) {
 

So I commented the call to XCheckIfEvent and sure enough the app does not hang
any more. So I guess the culprit is AWT. Looks like we will have to redo this
code. It looks like  Focus specific code. I will reassign to AWT. 

Sorry for the run-around, Jeremy's comments were very helpful.

###@###.### 2004-01-09

Name: dfR10261			Date: 01/28/2004


On Solaris The application hungs in native setNativeFontPath() function. Further 
investigation shows that application hungs in Xlib function XQueryExtension. Hung 
happens then LockDisplay(dpy) is invoked. I have tried to comment this macros in case 
of Display was already locked. After it application hungs then _XReply (dpy, (xReply 
*)&rep, 0, xTrue) was invoked.

###@###.### 2004-01-28

======================================================================

On Solaris 5.8, I am seeing the hang in XtDisplayInitialize() called in Java_sun_awt_motif_MToolkit_init(). XtDisplayInitialize() internally makes call to XInterAtom() and that's where the process hangs.
The output of truss attached to jnitest:
....
....
/1:     <- libXt:XtAppSetFallbackResources() = 0x1bb5f0
/1:     -> libXt:XtDisplayInitialize(0x1bb5f0, 0x98d30, 0xfb864118, 0xfb864128)
/1:       -> libX11:XCreateRegion(0x11da0c, 0xe6a74000, 0x98d30, 0x0)
/1:       <- libX11:XCreateRegion() = 0x1ba460
/1:       -> libX11:XDisplayKeycodes(0x98d30, 0x11d9c4, 0x11d9c8, 0x0)
/1:       <- libX11:XDisplayKeycodes() = 0x98d30
/1:       -> libX11:XrmStringToQuark(0xfb864118, 0x11d9c4, 0x11d9c8, 0x0)
/1:       -> libX11:_XrmInternalStringToQuark(0xfb864118, 0xc, 0x56df4, 0x0)
/1:       <- libX11:XrmStringToQuark() = 201
/1:       -> libX11:XrmStringToQuark(0xfb864128, 0xc9, 0xfb864124, 0x80000000)
/1:       -> libX11:_XrmInternalStringToQuark(0xfb864128, 0xc, 0x57d40, 0x0)
/1:       <- libX11:XrmStringToQuark() = 202
/1:       -> libX11:XInternAtom(0x98d30, 0xe6a5f500, 0x0, 0x80000000)
.......hangs here........

I generated the truss output with 1.3.1 also and the difference I notice here is that there is no XQueryExtension call made in 1.3.1 trace. 

###@###.### 2004-01-28

============================================================
The stack trace at the time of hang is:

libX11:_XReply(0x96db0, 0xffbed254, 0x0, 0x1)
libX11:XInternAtom (dpy, RCM_INIT, 0)     <<======================
libXt:InitPerDisplay(0x96db0, 0x173c40, 0x172180, 0x172180)
libXt:XtDisplayInitialize(0x173c40, 0x96db0, 0x172180, 0x172180)

The libX11:XInternAtom call made with the atom name "RCM_INIT" is waiting for reply from the X server which is never receives.

The code in libXt:InitPerDisplay() which is making call to XInternAtom is as follows:

#ifndef X_NO_RESOURCE_CONFIGURATION_MANAGEMENT
    pd->rcm_init = XInternAtom (dpy, RCM_INIT, 0);
    pd->rcm_data = XInternAtom (dpy, RCM_DATA, 0);
#endif

***** As I mentioned in my previous update that there is an XQueryExtension call being made from 142 JDK code that I don't see in the truss output of 131.

I tracked down that this call was being made from isDBESupported() in awt_GraphicsEnv.c. I commented out this code and with this change the 1.4.2 build also works fine. I don't see any hang after this modification. I still don't know the reason behind it. Probably the way we are making this call is not correct.

###@###.### 2004-01-29

Name: dfR10261			Date: 01/29/2004


Then I use 1.5 on Solaris application hungs 
in X11GraphicsEnvironment.setNativeFontPath() in static initialize block of MToolkit. 
After I comment this invocation application hungs in XtDisplayInitialize() which called 
in Java_sun_awt_motif_MToolkit_init(). After I comment XtDisplayInitialize() invocation 
hung occurs on XmGetFocusWidget() in check_for_focus_in() function in awt_TopLevel.c

###@###.### 2004-01-29

======================================================================

###@###.### 2004-01-29

There appears to be two seperate bugs here:

1. XCheckIfEvents() is called from Java with check_for_focus_in as the predicate
and this function calls Xlib calls which are not allowed by the predicate.

2. Another bug is causing hangs at different places in Xlib.  I think that
the cause of this bug is due to some issues with XdbeGetVisualInfo(). 
I have filed bug 4985837: XdbeGetVisualInfo causes Xlib threads to hang

In order to continue working on the first bug with XCheckIfEvents(), I have
attached a test libX11 for Solaris 8 sparc which unofficially fixes bug 4985837.
Please escalate bug 4985837 if fix for this bug is still needed after fixing
XCheckIfEvents() predicate problem.
======================================================

 I ran the testcase using the libX11.so given by Jeremy on solaris 5.8. It removes the hang at XtDisplayInitialize():

  * when run using local display the testcase does not hang at all, neither in XtDisplayInitialize() nor in XCheckIfEvents.

  * When run using remote display, it hangs in XCheckIfEvents.

Now the solution for the problem would be to remove XmGetFocusWidget() call from check_for_focus_in and use the cached data instead to get the window that has the keybord focus.

###@###.### 2004-01-30
======================================================

The predicate of XCheckIfEvent, check_for_focus_in(), always returns False even when it finds the matching FocusIn event. XCheckIfEvent calls predicate procedure for all the events in the queue until it returns True. So in our case, even after finding the mactched event, it gets called for the rest of the events also, as we are always returning False. It may cause performance degradation.

Probably this was done so as not to remove the FocusIn event from the queue(when predicate returns True, XCheckIfEvent removes the event from the queue), but this can be tackled by using XPutBackEvent which puts the event back into queue.

So the correct way should be to return True in predicate when we have found the
match and process the FocusIn event after the XCheckIfEvent call.

I tested jnitest, after doing the above mentioned modifications in awt_TopLevel.c and it works fine without any hang.

###@###.### 2004-02-03


Fix verified for build 1.4.2_05-ea-b01 on WinXP Home and RHEl 3 on Itanium
Raja Dhanesh
###@###.### 2004-04-29
                                     
2004-02-03
WORK AROUND

Name: pa48320			Date: 08/19/2003


None
======================================================================
                                     
2004-08-24
EVALUATION

Client code should not call XInitThreads().  
Documentation for XInitThreads() indicates that if it is used, it must be the 
first Xlib call.  By calling XInitThreads() a situation is created where 
threading related parts of the AWT Display structure were not initialized, 
but xlib locking is turned on.

###@###.### 2003-08-19

Here is a thread dump I took on RHAS2.1 with 1.4.2: 
It looks like it is blocking on our first call to Xlib. 

bash-2.05$ sh jnitest.sh
Full thread dump Java HotSpot(TM) Server VM (1.4.2-b28 mixed mode):

"Signal Dispatcher" daemon prio=1 tid=0x080b5658 nid=0x6432 waiting on condition [0..0]

"Finalizer" daemon prio=1 tid=0x080b12c8 nid=0x6430 in Object.wait() [58cc6000..58cc68c8]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x466a7c08> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
        - locked <0x466a7c08> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=1 tid=0x080b0e58 nid=0x642f in Object.wait() [58c45000..58c458c8]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x466a7c70> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:429)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:115)
        - locked <0x466a7c70> (a java.lang.ref.Reference$Lock)

"main" prio=1 tid=0x0804c960 nid=0x642c runnable [bffeb000..bffec2c8]
        at sun.awt.motif.MToolkit.init(Native Method)
        at sun.awt.motif.MToolkit.<init>(MToolkit.java:107)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
        at java.lang.Class.newInstance0(Class.java:308)
        at java.lang.Class.newInstance(Class.java:261)
        at java.awt.Toolkit$2.run(Toolkit.java:760)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:739)
        - locked <0x54b5a5b0> (a java.lang.Class)
        at java.awt.Window.getToolkit(Window.java:688)
        at java.awt.Window.init(Window.java:246)
        at java.awt.Window.<init>(Window.java:275)
        at java.awt.Frame.<init>(Frame.java:401)
        at java.awt.Frame.<init>(Frame.java:366)
        at javax.swing.JFrame.<init>(JFrame.java:154)
        at Test.<init>(Test.java:8)
        at Test.main(Test.java:36)

"VM Thread" prio=1 tid=0x080ae410 nid=0x642e runnable 

"VM Periodic Task Thread" prio=1 tid=0x080b9900 nid=0x6436 waiting on condition 
"Suspend Checker Thread" prio=1 tid=0x080b4be8 nid=0x6431 runnable 


I also tested with Tiger build 17 and XAWT.  It looks even more clear that our 
first call to Xlib blocks.  

"main" prio=1 tid=0x0804d658 nid=0x6543 runnable [bffec000..bffed608]
        at sun.awt.X11.XlibWrapper.XKeysymToKeycode(Native Method)
        at sun.awt.X11.XToolkit.keysymToPrimaryKeycode(XToolkit.java:1118)
        - locked <0x54dd08b8> (a java.lang.Class)
        at sun.awt.X11.XToolkit.setupModifierMap(XToolkit.java:1134)
        at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:102)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:141)
        at java.awt.Toolkit$2.run(Toolkit.java:786)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:769)
        - locked <0x54da4960> (a java.lang.Class)
        at java.awt.Window.getToolkit(Window.java:737)
        at java.awt.Window.init(Window.java:257)
        at java.awt.Window.<init>(Window.java:290)
        at java.awt.Frame.<init>(Frame.java:402)
        at java.awt.Frame.<init>(Frame.java:367)
        at javax.swing.JFrame.<init>(JFrame.java:154)
        at Test.<init>(Test.java:8)
        at Test.main(Test.java:36)

The test does execute with 1.3.1, but not 1.4.0.  

None of the printfs in jnitest.c fired, indicating that it blocked while calling 
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);   

###@###.### 2003-08-29

We can only reproduce this when running on Linux (e.g. RHAS 2.1) and remote 
display set to Solaris (e.g. S9U2).  We cannot reproduce it when running 
locally on Solaris, remote displaying between linux machines, or remote 
displaying from Solaris to Linux.  

I've reopened the bug.  I should note that XInitThreads is called before the 
VM is created, so it is, in fact, the first Xlib call.  

###@###.### 2003-09-02


I compiled the Xlib with Thread debugging enabled and looked at the output from
Xlib for the sample program provided, Below is the debug output when the hang occurs: 

PeekEvent.c line 46: thread d unlocking display
Pending.c line 38: thread d got display lock
Pending.c line 43: thread d unlocking display
NextEvent.c line 43: thread d got display lock
NextEvent.c line 50: thread d unlocking display
Context.c line 262: thread d got display lock
Context.c line 264: thread d unlocking display
ChkIfEv.c line 54: thread d got display lock
Xlib ERROR: Context.c line 262 thread d: locking display already locked at ChkIfEv.c line 54

These are both Xlib functions, so this might be an Xlib bug
###@###.### 2003-09-12

I talked to Alan Coopersmith from the X group and they suggested to file a bug.

###@###.### 2003-09-12

I have managed to prove that this is an Xlib bug : Look at the stack trace
below :

=>[1] __lwp_park(0x0, 0x0, 0x0, 0x0, 0x1, 0x22150), at 0xfea55dd4
  [2] mutex_lock_queue(0xfea68b44, 0x0, 0x11ae20, 0xfea68000, 0xff346310, 0xe49feab0), at 0xfea51bb4
  [3] slow_lock(0x11ae20, 0xfe8f1800, 0x106, 0xd, 0xff393430, 0x36), at 0xfea525b4
  [4] _XLockDisplayWarn(0x13ab48, 0xff393184, 0x106, 0x0, 0x586d53, 0x585300), at 0xff365314
  [5] _XLockDisplay(0x13ab48, 0xff393184, 0x106, 0xfbcf4000, 0xffdb5dc8, 0x0), at 0xff346310
  [6] XFindContext(0x13ab48, 0x2a8998, 0xfffffffd, 0xe447f02c, 0xfe231014, 0xe447f04c), at 0xff32c5b8
  [7] _XmGetWidgetExtData(0x2a8998, 0x3, 0x214c, 0xe4991660, 0xe470cccc, 0x2), at 0xe474ac4c
  [8] _XmGetFocusData(0x2a8998, 0x150588, 0x467cc8, 0x290070, 0x0, 0x0), at 0xe4759728
  [9] XmGetFocusWidget(0x2a8998, 0x6f, 0x56458, 0x7f, 0x291, 0x0), at 0xe47b5a8c
  [10] 0xe49a85a8(0xe4ce3a50, 0x19f5cc, 0xe447f440, 0x23ff70, 0xff346310, 0xe49feab0), at 0xe49a85a7
  [11] XCheckIfEvent(0x19f5cc, 0xe447f3e0, 0xe49a845c, 0xe447f440, 0x13ab48, 0xe447f45d), at 0xff339aa0
  [12] 0xe499f744(0x2f0250, 0x118f64, 0xe447f790, 0x2effa0, 0x0, 0x23ff70), at 0xe499f743
  [13] XtDispatchEventToWidget(0xe447f4cc, 0xe447f790, 0x63f80, 0xa, 0xe49feab0, 0xe4a029a0), at 0xfbcbe550
  [14] _XtDefaultDispatcher(0xe447f790, 0x0, 0xa, 0x290834, 0xfbcbd850, 0xe4a029a0), at 0xfbcbdf0c
  [15] XtDispatchEvent(0xe447f790, 0x44f6b0, 0x2f0250, 0xe4a02a08, 0xe499702c, 0x44f6b0), at 0xfbcbda34
  [16] 0xe49974a8(0x0, 0x67a28, 0x8, 0x358, 0xe49feab0, 0x23ff70), at 0xe49974a7
  [17] 0xe4996e24(0x23ff70, 0x13ab48, 0x0, 0x5, 0xe49feab0, 0xe4a03820), at 0xe4996e23
  [18] Java_sun_awt_motif_MToolkit_run(0x23ff70, 0xfedc3914, 0x67e84, 0xfee377c8


What is happening is that Xt calls XCheckIfEvent with a predicate function
that calls XFindContext. Since the XCheckIfEvent already called LockDisplay
and XFindContext  calls LockDisplay it gets blocked. This is because the default
mutex in pthreads is not recursive. They are using the default pthread_mutex
initializer. So to solve the problem they either need to use recursive mutexes
or change the code of XCheckIfEvent as below. 


------- ChkIfEv.c -------
*** /tmp/sccs.hVaaRi    Fri Sep 12 19:04:21 2003
--- ChkIfEv.c   Fri Sep 12 19:03:39 2003
***************
*** 57,69 ****
--- 57,72 ----
              for (qelt = prev ? prev->next : dpy->head;
                   qelt;
                   prev = qelt, qelt = qelt->next) {
+                 UnlockDisplay(dpy);
                  if(qelt->qserial_num > qe_serial
                     && (*predicate)(dpy, &qelt->event, arg)) {
+                     LockDisplay(dpy);
                      *event = qelt->event;
                      _XDeq(dpy, prev, qelt);
                      UnlockDisplay(dpy);
                      return True;
                  }
+                 LockDisplay(dpy);
              }
              if (prev)
                  qe_serial = prev->qserial_num;

With this change in place the testcase work fine without a hang.

###@###.### 2003-09-12 

I hope this is clear from the customer call record, but Oracle says they can 
easily reproduce the problem on Solaris 8 on a local display.  
###@###.### 2003-09-18

Adding the UnlockDisplay calls shown is not safe - if another thread modified 
the event linked list while the display is unlocked, the client could crash.
Transferring to the Motif group to determine if Motif can find a way to not make
calls that require getting the lock from the code being called from XCheckIfEvent.
###@###.### 2003-11-17


###@###.### 2003-12-01
Below are my investigation result.
1. Your new trace stack is not the same one as the original one when the bug reported. Moreover, the new deadlock shouldn't exist due to bug fix of 4041914
2. FindContext where display tried to be locked is invoked by callback, it should be impossible to avoid invoking it during the excuting of XCheckIfEvent.
3. For item 2, the original deadlock is hard to fix. The solution I can think out is to add thread mutex and unlock display before XFindContext like below. However, for this solution, libXm.so.4 need to be told if current display is locked before XFindeContext, and it's better that libX11 provide such an API, for example, Boolen XIfDispLocked(). From my investigation, I found there are some other similar bugs before(4041949, for instance). So, adding the API is worth and will not break the fundamental libX11 just as Alan hopes.

*** 659,666 ****
    XmAssocData  assocData = NULL;
    XmAssocData *assocDataPtr;
    XContext     widgetExtContext = ExtTypeToContext(extType);
!   
!   
    if ((XFindContext(XtDisplay(widget),
                    (Window) widget,
                    widgetExtContext,
--- 659,668 ----
    XmAssocData  assocData = NULL;
    XmAssocData *assocDataPtr;
    XContext     widgetExtContext = ExtTypeToContext(extType);
!  
!   _XmWidgetToAppContext(widget); 
!   _XmAppLock(app);
!   XUnlockDisplay(XtDisplay(widget));
    if ((XFindContext(XtDisplay(widget),
                    (Window) widget,
                    widgetExtContext,
***************
*** 669,678 ****
--- 671,684 ----
  #ifdef DEBUG
        XmeWarning(NULL, "no extension data on stack");
  #endif /* DEBUG */
+       XLockDisplay(XtDisplay(widget));
+       _XmAppUnlock(app);
        return NULL;
      }
    else
      {
+       XLockDisplay(XtDisplay(widget));
+       _XmAppUnlock(app);
        assocDataPtr = &assocData; 
        while ((*assocDataPtr)->next)
        assocDataPtr = &((*assocDataPtr)->next);



###@###.### 2004-01-08
The Xlib standard specification for XCheckIfEvents states:

  11.4.2.  Selecting Events Using a Predicate Procedure
  
  Each of the functions discussed in this section requires you
  to pass a predicate procedure that determines if an event
  matches what you want.  Your predicate procedure must decide
  if the event is useful without calling any Xlib functions.
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  If the predicate directly or indirectly causes the state of
  the event queue to change, the result is not defined.  If
  Xlib has been initialized for threads, the predicate is
  called with the display locked and the result of a call by
  the predicate to any Xlib function that locks the display is
  not defined unless the caller has first called XLockDisplay.

###@###.### 2004-01-09

If that's the case, then we need to find out who is calling XCheckIfEvents.
I used debug versions of libXm, libXt, and libX11, and I still get some 
functions that are unnamed.  These probably are coming from Java:

=>[6] _XLockDisplay(dpy = 0x136f10), line 491 in "locking.c"
  [7] XFindContext(display = 0x136f10, rid = 3316024U, context = -3, data = 0xe6980e70), line 262 in "Context.c"
  [8] _XmGetWidgetExtData(widget = 0x329938, extType = 3U), line 667 in "BaseClass.c"
  [9] _XmGetFocusData(wid = 0x329938), line 1079 in "Traversal.c"
  [10] XmGetFocusWidget(wid = 0x329938), line 1571 in "Traversal.c"
  [11] 0xfb9b6250(0x136f10, 0x61584, 0xe69812d8, 0xff1c597c, 0x82, 0x0), at 0xfb9b624f
  [12] XCheckIfEvent(dpy = 0x136f10, event = 0xe6981278, predicate = 0xfb9b6108, arg = 0xe69812d8 "\xe6\x98^V\x90^E\xc0"), line 61 in "ChkIfEv.c"
  [13] 0xfb9ad2d0(0x0, 0x93ee0, 0xe6981690, 0xe6981389, 0x22768, 0x0), at 0xfb9ad2cf
  [14] XtDispatchEventToWidget(widget = 0x329938, event = 0xe6981690), line 978 in "Event.c"
  [15] _XtDefaultDispatcher(event = 0xe6981690), line 1437 in "Event.c"
  [16] XtDispatchEvent(event = 0xe6981690), line 1517 in "Event.c"
  [17] 0xfb9a4e6c(0x1, 0x1, 0x33, 0xfb9e1224, 0x41a4, 0x0), at 0xfb9a4e6b
  [18] 0xfb9a4840(0x61f74, 0xfb9f80c4, 0x0, 0x0, 0x0, 0x0), at 0xfb9a483f
  [19] Java_sun_awt_motif_MToolkit_run(0x61f74, 0xe698188c, 0x0, 0x0, 0x0, 0x0), at 0xfb9a46b8

From the source of XtDispatchEventToWidget():

line 978:                    for (i = 0; i < numprocs && cont_to_disp; i++)
                        (*(proc[i]))(widget, closure[i], event, &cont_to_disp);

It appears to calling an event handler.  libXm and libXt add event handlers 
and those show up in dbx.  However, some handlers are not shown in dbx, 
so those may be coming from java:

(dbx) print proc[i]
proc[i] = 0xfb9ad180
(dbx) print proc[i-1]
proc[i-1] = 0xe6698dd0 = &_XmTrackShellFocus()
(dbx) print proc[i+1]
proc[i+1] = 0xfb83b4c4 = &_XtHandleFocus()
(dbx) print proc[i+2]
proc[i+2] = 0xff25c694 = &XFilterEvent()

Can someone from Java group please evaluate this?  I tried using a debug build of java, but could not get it to work.

==============================================================================
I looked at all the code in Java that calls XCheckIfEvent and I did find that
in one case, we DO call X from the predicate function. This happens in 
awt_TopLevel.c 

Lines 1227 onwards: 
        // This window lost focus. Find the opposite window which will
        // receive it
        XCheckIfEvent(awt_display, &inEvent, check_for_focus_in,
                      (XPointer)&focus_info);
        if (focus_info.inWin != None) {                
 
And the check_for_focus_in function does indeed call X11 :

static Bool
check_for_focus_in(Display * dpy, XEvent * eve
                                     
2004-08-24
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_05
generic
tiger-beta2

FIXED IN:
1.4.2_05
tiger-beta2

INTEGRATED IN:
1.4.2_05
tiger-b43
tiger-beta2

VERIFIED IN:
1.4.2_05


                                     
2004-08-24



Hardware and Software, Engineered to Work Together