summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS7
-rw-r--r--src/gtk2_in_qt4.cpp2
-rw-r--r--src/instance.c11
-rw-r--r--src/qt4_in_gtk2.cpp43
-rw-r--r--src/x11_in_gtk2.c43
-rw-r--r--src/x11_in_qt4.cpp2
-rw-r--r--wscript2
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 <d@drobilla.net>
+
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)