From 3723d115a6f4d30f652957d131c2a6ea56ad1dd0 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 24 Apr 2012 22:06:24 +0000 Subject: Fix crashes when wrapper widget is destroyed by toolkit before suil cleanup function is called. git-svn-id: http://svn.drobilla.net/lad/trunk/suil@4264 a436a847-0d15-0410-975c-d299462d15a1 --- NEWS | 7 +++++++ src/gtk2_in_qt4.cpp | 2 +- src/instance.c | 11 +++++++---- src/qt4_in_gtk2.cpp | 43 +++++++++++++++++++++++++------------------ src/x11_in_gtk2.c | 43 +++++++++++++++++++++++++++++++++++++------ src/x11_in_qt4.cpp | 2 +- wscript | 2 +- 7 files changed, 79 insertions(+), 31 deletions(-) diff --git a/NEWS b/NEWS index fc3e7d8..19fda32 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +suil (9999) stable; + + * Fix crashes when wrapper widget is destroyed by toolkit before + suil cleanup function is called. + + -- David Robillard + suil (0.6.0) stable; * Use path variables in pkgconfig files diff --git a/src/gtk2_in_qt4.cpp b/src/gtk2_in_qt4.cpp index 488614a..7629989 100644 --- a/src/gtk2_in_qt4.cpp +++ b/src/gtk2_in_qt4.cpp @@ -74,7 +74,7 @@ suil_wrapper_new(SuilHost* host, SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); wrapper->wrap = wrapper_wrap; - wrapper->free = (SuilWrapperFreeFunc)free; + wrapper->free = NULL; wrapper->impl = NULL; return wrapper; diff --git a/src/instance.c b/src/instance.c index f6824e8..57cb7e1 100644 --- a/src/instance.c +++ b/src/instance.c @@ -257,13 +257,16 @@ suil_instance_free(SuilInstance* instance) } free(instance->features); - if (instance->wrapper) { - instance->wrapper->free(instance->wrapper); - dlclose(instance->wrapper->lib); - } if (instance->handle) { instance->descriptor->cleanup(instance->handle); } + if (instance->wrapper) { + if (instance->wrapper->free) { + instance->wrapper->free(instance->wrapper); + } + dlclose(instance->wrapper->lib); + free(instance->wrapper); + } dlclose(instance->lib_handle); free(instance); } diff --git a/src/qt4_in_gtk2.cpp b/src/qt4_in_gtk2.cpp index eb2469a..4722413 100644 --- a/src/qt4_in_gtk2.cpp +++ b/src/qt4_in_gtk2.cpp @@ -34,6 +34,7 @@ struct _SuilQtWrapper { GtkSocket socket; QApplication* app; QX11EmbedWidget* qembed; + SuilWrapper* wrapper; SuilInstance* instance; }; @@ -46,19 +47,24 @@ GType suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER G_DEFINE_TYPE(SuilQtWrapper, suil_qt_wrapper, GTK_TYPE_SOCKET) static void -suil_qt_wrapper_dispose(GObject* gobject) +suil_qt_wrapper_finalize(GObject* gobject) { SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject); - if (self->qembed) { - delete self->qembed; - self->qembed = NULL; - - delete self->app; - self->app = NULL; + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = NULL; } - G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->dispose(gobject); + delete self->qembed; + self->qembed = NULL; + + delete self->app; + self->app = NULL; + + self->wrapper->impl = NULL; + + G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject); } static void @@ -66,7 +72,7 @@ suil_qt_wrapper_class_init(SuilQtWrapperClass* klass) { GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - gobject_class->dispose = suil_qt_wrapper_dispose; + gobject_class->finalize = suil_qt_wrapper_finalize; } static void @@ -94,6 +100,7 @@ wrapper_wrap(SuilWrapper* wrapper, SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); wrap->qembed = new QX11EmbedWidget(); + wrap->wrapper = wrapper; wrap->instance = instance; QWidget* qwidget = (QWidget*)instance->ui_widget; @@ -115,11 +122,10 @@ wrapper_wrap(SuilWrapper* wrapper, static void wrapper_free(SuilWrapper* wrapper) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER( - g_object_new(SUIL_TYPE_QT_WRAPPER, NULL)); - - gtk_object_destroy(GTK_OBJECT(wrap)); - free(wrap); + if (wrapper->impl) { + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } } SUIL_API @@ -130,15 +136,16 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features) { SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - wrapper->impl = NULL; + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + wrapper->impl = NULL; SuilQtWrapper* const wrap = SUIL_QT_WRAPPER( g_object_new(SUIL_TYPE_QT_WRAPPER, NULL)); static int argc = 0; - wrap->app = new QApplication(argc, NULL, true); + wrap->app = new QApplication(argc, NULL, true); + wrap->wrapper = NULL; wrapper->impl = wrap; diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c index 99308e7..e7b88ed 100644 --- a/src/x11_in_gtk2.c +++ b/src/x11_in_gtk2.c @@ -29,6 +29,7 @@ typedef struct _SuilX11WrapperClass SuilX11WrapperClass; struct _SuilX11Wrapper { GtkSocket socket; GtkPlug* plug; + SuilWrapper* wrapper; SuilInstance* instance; }; @@ -40,10 +41,28 @@ GType suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) +static gboolean +on_plug_removed(GtkSocket* sock, gpointer data) +{ + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); + + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = NULL; + } + + self->plug = NULL; + return TRUE; +} + static void -wrap_widget_dispose(GObject* gobject) +suil_x11_wrapper_finalize(GObject* gobject) { - G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->dispose(gobject); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); + + self->wrapper->impl = NULL; + + G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->finalize(gobject); } static void @@ -51,7 +70,7 @@ suil_x11_wrapper_class_init(SuilX11WrapperClass* klass) { GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - gobject_class->dispose = wrap_widget_dispose; + gobject_class->finalize = suil_x11_wrapper_finalize; } static void @@ -85,6 +104,7 @@ wrapper_wrap(SuilWrapper* wrapper, SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); instance->host_widget = GTK_WIDGET(wrap); + wrap->wrapper = wrapper; wrap->instance = instance; g_signal_connect_after(G_OBJECT(wrap), @@ -92,15 +112,24 @@ wrapper_wrap(SuilWrapper* wrapper, G_CALLBACK(suil_x11_wrapper_realize), NULL); + g_signal_connect(G_OBJECT(wrap), + "plug-removed", + G_CALLBACK(on_plug_removed), + NULL); + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - free(wrapper); + if (wrapper->impl) { + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } } + SUIL_API SuilWrapper* suil_wrapper_new(SuilHost* host, @@ -110,12 +139,14 @@ suil_wrapper_new(SuilHost* host, unsigned n_features) { SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER( g_object_new(SUIL_TYPE_X11_WRAPPER, NULL)); + wrap->wrapper = NULL; + wrapper->impl = wrap; wrapper->resize.handle = wrap; wrapper->resize.ui_resize = wrapper_resize; diff --git a/src/x11_in_qt4.cpp b/src/x11_in_qt4.cpp index d5ae534..dafb384 100644 --- a/src/x11_in_qt4.cpp +++ b/src/x11_in_qt4.cpp @@ -54,7 +54,7 @@ suil_wrapper_new(SuilHost* host, { SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); wrapper->wrap = wrapper_wrap; - wrapper->free = (SuilWrapperFreeFunc)free; + wrapper->free = NULL; QX11EmbedWidget* const ew = new QX11EmbedWidget(); diff --git a/wscript b/wscript index ff17f59..b92379f 100644 --- a/wscript +++ b/wscript @@ -7,7 +7,7 @@ from waflib.extras import autowaf as autowaf import waflib.Logs as Logs, waflib.Options as Options # Version of this package (even if built as a child) -SUIL_VERSION = '0.6.0' +SUIL_VERSION = '0.6.1' SUIL_MAJOR_VERSION = '0' # Library version (UNIX style major, minor, micro) -- cgit v1.2.1