Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonny Lamb2015-03-04 13:41:42 +0000
committerAlexander Kurtakov2015-03-24 08:31:06 +0000
commite9c202445b7800e816318f00aed3887885c67efd (patch)
tree0752d8346f152a04670bb375ae95929e98ed6503
parent9d92881b3b42b42f713c6b2022fdd425b5bdd96e (diff)
downloadeclipse.platform.swt-e9c202445b7800e816318f00aed3887885c67efd.tar.gz
eclipse.platform.swt-e9c202445b7800e816318f00aed3887885c67efd.tar.xz
eclipse.platform.swt-e9c202445b7800e816318f00aed3887885c67efd.zip
Bug 427776 - [GTK3] JVM running Eclipse crashes several times per day to
SIGSEGV in gdk_window_get_support_multidevice * Fixed 32bit compliance. * Guard the code for GTK 3.0-3.11.9 Change-Id: I2e11cf20b1df6743e714b48f51dd2ee79544bdce Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> Signed-off-by: Alexander Kurtakov <akurtako@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c20
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java13
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java66
6 files changed, 102 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index 7c5fd0ec65..6085c5d1ec 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
@@ -3124,6 +3124,26 @@ JNIEXPORT void JNICALL OS_NATIVE(_1g_1free)
}
#endif
+#ifndef NO__1g_1hash_1table_1get_1values
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1hash_1table_1get_1values)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1hash_1table_1get_1values_FUNC);
+/*
+ rc = (jintLong)g_hash_table_get_values((GHashTable *)arg0);
+*/
+ {
+ OS_LOAD_FUNCTION(fp, g_hash_table_get_values)
+ if (fp) {
+ rc = (jintLong)((jintLong (CALLING_CONVENTION*)(GHashTable *))fp)((GHashTable *)arg0);
+ }
+ }
+ OS_NATIVE_EXIT(env, that, _1g_1hash_1table_1get_1values_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1icon_1new_1for_1string
JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1icon_1new_1for_1string)
(JNIEnv *env, jclass that, jbyteArray arg0, jintLongArray arg1)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
index 7473872fe0..06f37e1f44 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
@@ -92,6 +92,7 @@
#define g_dbus_proxy_new_finish_LIB LIB_GIO
#define g_dbus_proxy_new_sync_LIB LIB_GIO
#define g_filename_display_name_LIB LIB_GLIB
+#define g_hash_table_get_values_LIB LIB_GLIB
#define g_thread_init_LIB LIB_GTHREAD
#define g_variant_get_boolean_LIB LIB_GIO
#define g_variant_get_child_value_LIB LIB_GIO
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index bc2e24b2e4..fa3082b6b9 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
@@ -248,6 +248,7 @@ char * OS_nativeFunctionNames[] = {
"_1g_1filename_1to_1uri",
"_1g_1filename_1to_1utf8",
"_1g_1free",
+ "_1g_1hash_1table_1get_1values",
"_1g_1icon_1new_1for_1string",
"_1g_1icon_1to_1string",
"_1g_1idle_1add",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index 036d49d302..4aa6f8e734 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
@@ -258,6 +258,7 @@ typedef enum {
_1g_1filename_1to_1uri_FUNC,
_1g_1filename_1to_1utf8_FUNC,
_1g_1free_FUNC,
+ _1g_1hash_1table_1get_1values_FUNC,
_1g_1icon_1new_1for_1string_FUNC,
_1g_1icon_1to_1string_FUNC,
_1g_1idle_1add_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index 8fedc5d423..dde3910691 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -2551,6 +2551,19 @@ public static final void g_free(long /*int*/ mem) {
}
}
/**
+ * @method flags=dynamic
+ * @param table cast=(GHashTable *)
+ */
+public static final native long /*int*/ _g_hash_table_get_values(long /*int*/ table);
+public static final long /*int*/ g_hash_table_get_values(long /*int*/ table) {
+ lock.lock();
+ try {
+ return _g_hash_table_get_values(table);
+ } finally {
+ lock.unlock();
+ }
+}
+/**
* @param function cast=(GSourceFunc)
* @param data cast=(gpointer)
*/
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index 375855262c..b61e4f4233 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
@@ -47,6 +47,7 @@ public abstract class Control extends Widget implements Drawable {
long /*int*/ fixedHandle;
long /*int*/ redrawWindow, enableWindow, provider;
int drawCount, backgroundAlpha = 255;
+ long /*int*/ enterNotifyEventId;
Composite parent;
Cursor cursor;
Menu menu;
@@ -58,6 +59,23 @@ public abstract class Control extends Widget implements Drawable {
Accessible accessible;
Control labelRelation;
+ /* these class variables are for the workaround for bug #427776 */
+ static Callback enterNotifyEventFunc;
+ static final int enterNotifyEventSignalId;
+ static final int GTK_POINTER_WINDOW;
+ static final int SWT_GRAB_WIDGET;
+ static {
+ enterNotifyEventFunc = new Callback (Control.class, "enterNotifyEventProc", 4);
+ if (enterNotifyEventFunc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+ enterNotifyEventSignalId = OS.g_signal_lookup (OS.enter_notify_event, OS.GTK_TYPE_WIDGET ());
+
+ byte [] buffer = Converter.wcsToMbcs (null, "gtk-pointer-window", true);
+ GTK_POINTER_WINDOW = OS.g_quark_from_string (buffer);
+ buffer = Converter.wcsToMbcs (null, "swt-grab-widget", true);
+ SWT_GRAB_WIDGET = OS.g_quark_from_string (buffer);
+ }
+
Control () {
}
@@ -4295,6 +4313,29 @@ public void setDragDetect (boolean dragDetect) {
}
}
+static long /*int*/ enterNotifyEventProc (long /*int*/ ihint, long /*int*/ n_param_values, long /*int*/ param_values, long /*int*/ data) {
+ /* 427776: this workaround listens to the enter-notify-event signal on all
+ * GtkWidgets. If enableWindow (the data parameter) has been added to the
+ * internal hash table of the widget, a record is kept as the lifetime of
+ * enableWindow is controlled here, so we'll need to remove that reference
+ * when we destroy enableWindow. this internal hash table was removed in
+ * GTK 3.11.9 so once only newer GTK is targeted, this workaround can be
+ * removed. */
+ long /*int*/ instance = OS.g_value_peek_pointer (param_values);
+ long /*int*/ hashTable = OS.g_object_get_qdata (instance, GTK_POINTER_WINDOW);
+
+ // there will only ever be one item in the hash table
+ if (hashTable != 0) {
+ long /*int*/ firstItem = OS.g_hash_table_get_values (hashTable);
+ long /*int*/ gdkWindow = OS.g_list_data (firstItem);
+ // data is actually enableWindow
+ if (gdkWindow == data)
+ OS.g_object_set_qdata(gdkWindow, SWT_GRAB_WIDGET, instance);
+ }
+
+ return 1; // keep the signal connected
+}
+
/**
* Enables the receiver if the argument is <code>true</code>,
* and disables it otherwise. A disabled control is typically
@@ -4328,6 +4369,24 @@ public void setEnabled (boolean enabled) {
if (isDisposed ()) return;
if (enabled) {
if (enableWindow != 0) {
+ if (OS.GTK3 && OS.GTK_VERSION < OS.VERSION (3, 11, 9)) {
+ if (enterNotifyEventId > 0)
+ OS.g_signal_remove_emission_hook(enterNotifyEventSignalId, enterNotifyEventId);
+ enterNotifyEventId = 0;
+
+ /*
+ * 427776: now we can remove any reference to the GdkWindow
+ * in a widget's internal hash table. this internal hash
+ * table was removed in GTK 3.11.9 so once only newer GTK is
+ * targeted, this workaround can be removed.
+ */
+ long /*int*/ grabWidget = OS.g_object_get_qdata(enableWindow, SWT_GRAB_WIDGET);
+ if (grabWidget != 0) {
+ OS.g_object_set_qdata(grabWidget, GTK_POINTER_WINDOW, 0);
+ OS.g_object_set_qdata(enableWindow, SWT_GRAB_WIDGET, 0);
+ }
+ }
+
OS.gdk_window_set_user_data (enableWindow, 0);
OS.gdk_window_destroy (enableWindow);
enableWindow = 0;
@@ -4349,6 +4408,13 @@ public void setEnabled (boolean enabled) {
attributes.window_type = OS.GDK_WINDOW_CHILD;
enableWindow = OS.gdk_window_new (window, attributes, OS.GDK_WA_X | OS.GDK_WA_Y);
if (enableWindow != 0) {
+ /* 427776: we need to listen to all enter-notify-event signals to
+ * see if this new GdkWindow has been added to a widget's internal
+ * hash table, so when the GdkWindow is destroyed we can also remove
+ * that reference. */
+ if (OS.GTK3 && OS.GTK_VERSION < OS.VERSION (3, 11, 9))
+ enterNotifyEventId = OS.g_signal_add_emission_hook (enterNotifyEventSignalId, 0, enterNotifyEventFunc.getAddress (), enableWindow, 0);
+
OS.gdk_window_set_user_data (enableWindow, parentHandle);
if (!OS.GDK_WINDOWING_X11 ()) {
OS.gdk_window_raise (enableWindow);

Back to the top