[brasero] Fix #599655 - brasero crashed with SIGSEGV in g_main_context_dispatch()
- From: Philippe Rouquier <philippr src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [brasero] Fix #599655 - brasero crashed with SIGSEGV in g_main_context_dispatch()
- Date: Wed, 4 Nov 2009 14:28:16 +0000 (UTC)
commit c9284f714e146a27316db4ced465797331bd1b61
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date: Wed Nov 4 15:00:24 2009 +0100
Fix #599655 - brasero crashed with SIGSEGV in g_main_context_dispatch()
Prevent brasero from returning concurent errors for video and audio projects.
libbrasero-burn/brasero-data-session.c | 2 +-
libbrasero-burn/brasero-data-vfs.c | 4 +-
libbrasero-burn/brasero-track-stream-cfg.c | 21 ++++--
libbrasero-utils/brasero-io.c | 125 +++++++++++++++++++---------
libbrasero-utils/brasero-io.h | 29 ++++++-
src/brasero-audio-disc.c | 4 +-
src/brasero-player.c | 2 +-
src/brasero-playlist.c | 2 +-
src/brasero-project-manager.c | 2 +-
src/brasero-video-disc.c | 3 +-
10 files changed, 137 insertions(+), 57 deletions(-)
---
diff --git a/libbrasero-burn/brasero-data-session.c b/libbrasero-burn/brasero-data-session.c
index 8b31af3..318d4b0 100644
--- a/libbrasero-burn/brasero-data-session.c
+++ b/libbrasero-burn/brasero-data-session.c
@@ -530,7 +530,7 @@ brasero_data_session_stop_io (BraseroDataSession *self)
if (priv->load_dir) {
brasero_io_cancel_by_base (priv->load_dir);
- g_free (priv->load_dir);
+ brasero_io_job_base_free (priv->load_dir);
priv->load_dir = NULL;
}
}
diff --git a/libbrasero-burn/brasero-data-vfs.c b/libbrasero-burn/brasero-data-vfs.c
index f2c58f1..29564c0 100644
--- a/libbrasero-burn/brasero-data-vfs.c
+++ b/libbrasero-burn/brasero-data-vfs.c
@@ -983,13 +983,13 @@ brasero_data_vfs_clear (BraseroDataVFS *self)
/* Stop all VFS operations */
if (priv->load_uri) {
brasero_io_cancel_by_base (priv->load_uri);
- g_free (priv->load_uri);
+ brasero_io_job_base_free (priv->load_uri);
priv->load_uri = NULL;
}
if (priv->load_contents) {
brasero_io_cancel_by_base (priv->load_contents);
- g_free (priv->load_contents);
+ brasero_io_job_base_free (priv->load_contents);
priv->load_contents = NULL;
}
diff --git a/libbrasero-burn/brasero-track-stream-cfg.c b/libbrasero-burn/brasero-track-stream-cfg.c
index 7efc348..cec718a 100644
--- a/libbrasero-burn/brasero-track-stream-cfg.c
+++ b/libbrasero-burn/brasero-track-stream-cfg.c
@@ -45,6 +45,8 @@
#include "brasero-io.h"
#include "brasero-tags.h"
+static BraseroIOJobCallbacks *io_methods = NULL;
+
typedef struct _BraseroTrackStreamCfgPrivate BraseroTrackStreamCfgPrivate;
struct _BraseroTrackStreamCfgPrivate
{
@@ -304,11 +306,14 @@ brasero_track_stream_cfg_get_info (BraseroTrackStreamCfg *track)
}
/* get info async for the file */
- if (!priv->load_uri)
- priv->load_uri = brasero_io_register (G_OBJECT (track),
- brasero_track_stream_cfg_results_cb,
- NULL,
- NULL);
+ if (!priv->load_uri) {
+ if (!io_methods)
+ io_methods = brasero_io_register_job_methods (brasero_track_stream_cfg_results_cb,
+ NULL,
+ NULL);
+
+ priv->load_uri = brasero_io_register_with_methods (G_OBJECT (track), io_methods);
+ }
priv->loading = TRUE;
uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE);
@@ -388,7 +393,11 @@ brasero_track_stream_cfg_finalize (GObject *object)
if (priv->load_uri) {
brasero_io_cancel_by_base (priv->load_uri);
- g_free (priv->load_uri);
+
+ if (io_methods->ref == 1)
+ io_methods = NULL;
+
+ brasero_io_job_base_free (priv->load_uri);
priv->load_uri = NULL;
}
diff --git a/libbrasero-utils/brasero-io.c b/libbrasero-utils/brasero-io.c
index 16240b4..b7c8b15 100644
--- a/libbrasero-utils/brasero-io.c
+++ b/libbrasero-utils/brasero-io.c
@@ -187,9 +187,9 @@ brasero_io_job_progress_report_cb (gpointer callback_data)
/* update our progress */
progress->progress (progress->job, progress);
- progress->job->base->progress (progress->job->base->object,
- progress,
- callback_data);
+ progress->job->base->methods->progress (progress->job->base->object,
+ progress,
+ callback_data);
}
g_mutex_unlock (priv->lock);
@@ -206,7 +206,7 @@ brasero_io_job_progress_report_start (BraseroIO *self,
priv = BRASERO_IO_PRIVATE (self);
- if (!job->base->progress)
+ if (!job->base->methods->progress)
return;
progress = g_new0 (BraseroIOJobProgress, 1);
@@ -326,8 +326,6 @@ brasero_io_return_result_idle (gpointer callback_data)
BraseroIOJobResult *result;
BraseroIOPrivate *priv;
guint results_id;
- GSList *iter;
- GSList *next;
int i;
priv = BRASERO_IO_PRIVATE (self);
@@ -336,62 +334,72 @@ brasero_io_return_result_idle (gpointer callback_data)
/* Put that to 0 for now so that a new idle call will be scheduled while
* we are in the loop. That way if we block the other one will be able
- * to deliver the results. */
+ * to deliver results. */
results_id = priv->results_id;
priv->results_id = 0;
/* Return several results at a time that can be a huge speed gain.
* What should be the value that provides speed and responsiveness? */
- for (i = 0, iter = priv->results; iter && i < NUMBER_OF_RESULTS; iter = next) {
+ for (i = 0; priv->results && i < NUMBER_OF_RESULTS;) {
BraseroIOJobBase *base;
+ GSList *iter;
- result = iter->data;
- next = iter->next;
+ /* Find the next result that can be returned */
+ result = NULL;
+ for (iter = priv->results; iter; iter = iter->next) {
+ BraseroIOJobResult *tmp_result;
+
+ tmp_result = iter->data;
+ if (!tmp_result->base->methods->in_use) {
+ result = tmp_result;
+ break;
+ }
+ }
+
+ if (!result)
+ break;
/* Make sure another result is not returned for this base. This
* is to avoid BraseroDataDisc showing multiple dialogs for
* various problems; like one dialog for joliet, one for deep,
* and one for name collision. */
- if (result->base->in_use)
- continue;
+ base = (BraseroIOJobBase *) result->base;
+ base->methods->in_use = TRUE;
priv->results = g_slist_remove (priv->results, result);
- base = (BraseroIOJobBase *) result->base;
- base->in_use = TRUE;
+ /* This is to make sure the object
+ * lives as long as we need it. */
+ g_object_ref (base->object);
g_mutex_unlock (priv->lock);
data = result->callback_data;
- /* This is to make sure the object lives
- * as long as we need it. */
- g_object_ref (base->object);
-
if (result->uri || result->info || result->error)
- base->callback (base->object,
- result->error,
- result->uri,
- result->info,
- data? data->callback_data:NULL);
+ base->methods->callback (base->object,
+ result->error,
+ result->uri,
+ result->info,
+ data? data->callback_data:NULL);
/* call destroy () for callback data */
brasero_io_unref_result_callback_data (data,
base->object,
- base->destroy,
+ base->methods->destroy,
FALSE);
- g_object_unref (base->object);
-
brasero_io_job_result_free (result);
g_mutex_lock (priv->lock);
i ++;
- base->in_use = FALSE;
+
+ g_object_unref (base->object);
+ base->methods->in_use = FALSE;
}
- if (!priv->results_id && iter && i >= NUMBER_OF_RESULTS) {
+ if (!priv->results_id && priv->results && i >= NUMBER_OF_RESULTS) {
/* There are still results and no idle call is scheduled so we
* have to restart ourselves to make sure we empty the queue */
priv->results_id = results_id;
@@ -519,10 +527,10 @@ brasero_io_job_free (gboolean cancelled,
* add a dummy result to destroy callback_data. */
if (g_atomic_int_dec_and_test (&job->callback_data->ref)) {
if (cancelled) {
- if (job->base->destroy)
- job->base->destroy (job->base->object,
- TRUE,
- job->callback_data->callback_data);
+ if (job->base->methods->destroy)
+ job->base->methods->destroy (job->base->object,
+ TRUE,
+ job->callback_data->callback_data);
g_free (job->callback_data);
}
@@ -2169,7 +2177,7 @@ brasero_io_cancel_result (BraseroIO *self,
data = result->callback_data;
brasero_io_unref_result_callback_data (data,
result->base->object,
- result->base->destroy,
+ result->base->methods->destroy,
TRUE);
brasero_io_job_result_free (result);
}
@@ -2312,23 +2320,60 @@ brasero_io_find_urgent (const BraseroIOJobBase *base,
}
+BraseroIOJobCallbacks *
+brasero_io_register_job_methods (BraseroIOResultCallback callback,
+ BraseroIODestroyCallback destroy,
+ BraseroIOProgressCallback progress)
+{
+ BraseroIOJobCallbacks *methods;
+
+ methods = g_new0 (BraseroIOJobCallbacks, 1);
+ methods->callback = callback;
+ methods->destroy = destroy;
+ methods->progress = progress;
+
+ return methods;
+}
+
BraseroIOJobBase *
-brasero_io_register (GObject *object,
- BraseroIOResultCallback callback,
- BraseroIODestroyCallback destroy,
- BraseroIOProgressCallback progress)
+brasero_io_register_with_methods (GObject *object,
+ BraseroIOJobCallbacks *methods)
{
BraseroIOJobBase *base;
base = g_new0 (BraseroIOJobBase, 1);
base->object = object;
- base->callback = callback;
- base->destroy = destroy;
- base->progress = progress;
+ base->methods = methods;
+ methods->ref ++;
return base;
}
+BraseroIOJobBase *
+brasero_io_register (GObject *object,
+ BraseroIOResultCallback callback,
+ BraseroIODestroyCallback destroy,
+ BraseroIOProgressCallback progress)
+{
+ return brasero_io_register_with_methods (object, brasero_io_register_job_methods (callback, destroy, progress));
+}
+
+void
+brasero_io_job_base_free (BraseroIOJobBase *base)
+{
+ BraseroIOJobCallbacks *methods;
+
+ if (!base)
+ return;
+
+ methods = base->methods;
+ g_free (base);
+
+ methods->ref --;
+ if (methods->ref <= 0)
+ g_free (methods);
+}
+
static int
brasero_io_xid_for_metadata (gpointer user_data)
{
diff --git a/libbrasero-utils/brasero-io.h b/libbrasero-utils/brasero-io.h
index 3c50f84..ba32da8 100644
--- a/libbrasero-utils/brasero-io.h
+++ b/libbrasero-utils/brasero-io.h
@@ -112,15 +112,22 @@ typedef gboolean (*BraseroIOCompareCallback) (gpointer data,
gpointer user_data);
-struct _BraseroIOJobBase {
- GObject *object;
+struct _BraseroIOJobCallbacks {
BraseroIOResultCallback callback;
BraseroIODestroyCallback destroy;
BraseroIOProgressCallback progress;
+ guint ref;
+
/* Whether we are returning something for this base */
guint in_use:1;
};
+typedef struct _BraseroIOJobCallbacks BraseroIOJobCallbacks;
+
+struct _BraseroIOJobBase {
+ GObject *object;
+ BraseroIOJobCallbacks *methods;
+};
typedef struct _BraseroIOJobBase BraseroIOJobBase;
struct _BraseroIOResultCallbackData {
@@ -172,12 +179,30 @@ brasero_io_set_parent_window_callback (BraseroIOGetParentWinCb callback,
void
brasero_io_shutdown (void);
+/* NOTE: The split in methods and objects was
+ * done to prevent jobs sharing the same methods
+ * to return their results concurently. In other
+ * words only one job among those sharing the
+ * same methods can return its results. */
+
BraseroIOJobBase *
brasero_io_register (GObject *object,
BraseroIOResultCallback callback,
BraseroIODestroyCallback destroy,
BraseroIOProgressCallback progress);
+BraseroIOJobBase *
+brasero_io_register_with_methods (GObject *object,
+ BraseroIOJobCallbacks *methods);
+
+BraseroIOJobCallbacks *
+brasero_io_register_job_methods (BraseroIOResultCallback callback,
+ BraseroIODestroyCallback destroy,
+ BraseroIOProgressCallback progress);
+
+void
+brasero_io_job_base_free (BraseroIOJobBase *base);
+
void
brasero_io_cancel_by_data (gpointer callback_data);
diff --git a/src/brasero-audio-disc.c b/src/brasero-audio-disc.c
index 6994ea6..5de8a54 100644
--- a/src/brasero-audio-disc.c
+++ b/src/brasero-audio-disc.c
@@ -541,8 +541,8 @@ brasero_audio_disc_finalize (GObject *object)
brasero_audio_disc_reset_real (cobj);
- g_free (cobj->priv->add_dir);
- g_free (cobj->priv->add_playlist);
+ brasero_io_job_base_free (cobj->priv->add_dir);
+ brasero_io_job_base_free (cobj->priv->add_playlist);
cobj->priv->add_dir = NULL;
cobj->priv->add_playlist = NULL;
diff --git a/src/brasero-player.c b/src/brasero-player.c
index d8901e8..5e58295 100644
--- a/src/brasero-player.c
+++ b/src/brasero-player.c
@@ -1285,7 +1285,7 @@ brasero_player_destroy (GtkObject *obj)
if (player->priv->meta_task){
brasero_io_cancel_by_base (player->priv->meta_task);
- g_free (player->priv->meta_task);
+ brasero_io_job_base_free (player->priv->meta_task);
player->priv->meta_task = 0;
}
diff --git a/src/brasero-playlist.c b/src/brasero-playlist.c
index 82275f4..7cb10de 100644
--- a/src/brasero-playlist.c
+++ b/src/brasero-playlist.c
@@ -437,7 +437,7 @@ brasero_playlist_destroy (GtkObject *object)
* raise problems since the GdkWindow has been destroyed */
if (playlist->priv->parse_type) {
brasero_io_cancel_by_base (playlist->priv->parse_type);
- g_free (playlist->priv->parse_type);
+ brasero_io_job_base_free (playlist->priv->parse_type);
playlist->priv->parse_type = NULL;
}
diff --git a/src/brasero-project-manager.c b/src/brasero-project-manager.c
index e245fd9..3cb9ec9 100644
--- a/src/brasero-project-manager.c
+++ b/src/brasero-project-manager.c
@@ -1017,7 +1017,7 @@ brasero_project_manager_finalize (GObject *object)
if (cobj->priv->size_preview) {
brasero_io_cancel_by_base (cobj->priv->size_preview);
- g_free (cobj->priv->size_preview);
+ brasero_io_job_base_free (cobj->priv->size_preview);
cobj->priv->size_preview = NULL;
}
diff --git a/src/brasero-video-disc.c b/src/brasero-video-disc.c
index 3350bd7..e1ce3bc 100644
--- a/src/brasero-video-disc.c
+++ b/src/brasero-video-disc.c
@@ -1276,7 +1276,8 @@ brasero_video_disc_finalize (GObject *object)
priv = BRASERO_VIDEO_DISC_PRIVATE (object);
if (priv->load_dir) {
- g_free (priv->load_dir);
+ brasero_io_cancel_by_base (priv->load_dir);
+ brasero_io_job_base_free (priv->load_dir);
priv->load_dir = NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]