JDK-6966643 : GTK FileDialog hangs when user manually closes it
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2010-07-05
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
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.
JDK 7
7 b102Fixed
Related Reports
Relates :  
Description
TESTCASE:

import java.awt.*;

public class test{
    public static final void main(String args[]){
        Frame f = new Frame();
        FileDialog d = new FileDialog(f);
        d.setVisible(true);
    }
}

STEPS TO REPRODUCE:

1. a file dialog opens
2. close the dialog by ESC and the dialog hangs

easily reproducible with GTK file dialogs starting from jdk 7 b100

Comments
EVALUATION Note that we aren't able to use reentrant locks as it's currently not implemented in GTK (https://bugzilla.gnome.org/show_bug.cgi?id=425995).
20-07-2010

EVALUATION Introduced by the fix for http://monaco.sfbay/detail.jsf?cr=6959165 - the fix surrounds the gtk_widget_hide() call (and some other GTK calls) with a gdk_threads_enter()/gdk_threads_leave() pair. The problem is that this pair is needed only if the GTK functions are executed outside of the main GTK lock. Callbacks from GTK signals are made within the GTK lock. So, within a signal handler there is no need to call gdk_threads_enter() / gdk_threads_leave() (http://www.gtk.org/api/2.6/gdk/gdk-Threads.html) Apparently, the default implementation of the GTK lock functions isn't reentrant and the additional pair of the gdk_threads_enter() / gdk_threads_leave() causes hang.
05-07-2010

SUGGESTED FIX $ hg diff src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c diff -r f5145c7119c2 src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c --- a/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Thu Jun 24 11:50:18 2010 +0400 +++ b/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Mon Jul 05 13:08:22 2010 +0400 @@ -42,6 +42,29 @@ static gboolean filenameFilterCallback(c filename); } +static void quit(gboolean isSignalHandler) +{ + if (dialog != NULL) + { + // Callbacks from GTK signals are made within the GTK lock + // So, within a signal handler there is no need to call + // gdk_threads_enter() / fp_gdk_threads_leave() + if (isSignalHandler == FALSE) { + fp_gdk_threads_enter(); + } + + fp_gtk_widget_hide (dialog); + fp_gtk_widget_destroy (dialog); + + fp_gtk_main_quit (); + dialog = NULL; + + if (isSignalHandler == FALSE) { + fp_gdk_threads_leave(); + } + } +} + /* * Class: sun_awt_X11_GtkFileDialogPeer * Method: quit @@ -50,18 +73,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit (JNIEnv * env, jobject jpeer) { - if (dialog != NULL) - { - fp_gdk_threads_enter(); - - fp_gtk_widget_hide (dialog); - fp_gtk_widget_destroy (dialog); - - fp_gtk_main_quit (); - dialog = NULL; - - fp_gdk_threads_leave(); - } + quit(FALSE); } /** @@ -147,7 +159,7 @@ static void handle_response(GtkWidget* a jfilenames); fp_g_free(current_folder); - Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL); + quit(TRUE); } /*
05-07-2010