diff options
| author | Jonny Lamb | 2015-03-04 13:41:42 +0000 |
|---|---|---|
| committer | Alexander Kurtakov | 2015-03-24 08:31:06 +0000 |
| commit | e9c202445b7800e816318f00aed3887885c67efd (patch) | |
| tree | 0752d8346f152a04670bb375ae95929e98ed6503 | |
| parent | 9d92881b3b42b42f713c6b2022fdd425b5bdd96e (diff) | |
| download | eclipse.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>
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); |
