src/solaris/native/sun/awt/gtk2_interface.c
Print this page
@@ -79,11 +79,11 @@
const gint SELECTED = 1 << 9;
const gint DEFAULT = 1 << 10;
static void *gtk2_libhandle = NULL;
static void *gthread_libhandle = NULL;
-static gboolean flag_g_thread_get_initialized = FALSE;
+
static jmp_buf j;
/* Widgets */
static GtkWidget *gtk2_widget = NULL;
static GtkWidget *gtk2_window = NULL;
@@ -500,11 +500,11 @@
fp_gtk_file_chooser_get_filenames = dl_symbol(
"gtk_file_chooser_get_filenames");
fp_gtk_g_slist_length = dl_symbol("g_slist_length");
}
-gboolean gtk2_load()
+gboolean gtk2_load(JNIEnv *env)
{
gboolean result;
int i;
int (*handler)();
int (*io_handler)();
@@ -531,10 +531,11 @@
if (fp_gtk_check_version(2, 2, 0)) {
longjmp(j, NO_SYMBOL_EXCEPTION);
}
/* GLib */
+ fp_glib_check_version = dl_symbol("glib_check_version");
fp_g_free = dl_symbol("g_free");
fp_g_object_unref = dl_symbol("g_object_unref");
fp_g_main_context_iteration =
dl_symbol("g_main_context_iteration");
@@ -706,10 +707,13 @@
fp_gtk_main = dl_symbol("gtk_main");
/**
* GLib thread system
*/
+ if (fp_glib_check_version(2, 20, 0) == NULL) {
+ fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized");
+ }
fp_g_thread_init = dl_symbol_gthread("g_thread_init");
fp_gdk_threads_init = dl_symbol("gdk_threads_init");
fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");
@@ -808,20 +812,35 @@
*/
handler = XSetErrorHandler(NULL);
io_handler = XSetIOErrorHandler(NULL);
if (fp_gtk_check_version(2, 2, 0) == NULL) {
+ jclass clazz = (*env)->FindClass(env, "sun/misc/GThreadHelper");
+ jmethodID mid_getInitStateAndInitialize = (*env)->GetStaticMethodID(env, clazz, "getInitStateAndInitialize", "()Z");
+ jmethodID mid_lock = (*env)->GetStaticMethodID(env, clazz, "lock", "()V");
+ jmethodID mid_unlock = (*env)->GetStaticMethodID(env, clazz, "unlock", "()V");
+
// Init the thread system to use GLib in a thread-safe mode
- if (!flag_g_thread_get_initialized) {
- flag_g_thread_get_initialized = TRUE;
+ (*env)->CallStaticVoidMethod(env, clazz, mid_lock);
+
+ // Calling g_thread_init() multiple times leads to crash on GLib < 2.24
+ // We can use g_thread_get_initialized () but it is available only for
+ // GLib >= 2.20. We rely on GThreadHelper for GLib < 2.20.
+ gboolean is_g_thread_get_initialized = FALSE;
+ if (fp_glib_check_version(2, 20, 0) == NULL) {
+ is_g_thread_get_initialized = fp_g_thread_get_initialized();
+ }
+ if (!(*env)->CallStaticBooleanMethod(env, clazz, mid_getInitStateAndInitialize)
+ && !is_g_thread_get_initialized) {
fp_g_thread_init(NULL);
//According the GTK documentation, gdk_threads_init() should be
//called before gtk_init() or gtk_init_check()
fp_gdk_threads_init();
}
+ (*env)->CallStaticVoidMethod(env, clazz, mid_unlock);
}
result = (*fp_gtk_init_check)(NULL, NULL);
XSetErrorHandler(handler);
XSetIOErrorHandler(io_handler);