I have taken `apt-get source evolution-data-server` on an up to date Bullseye 
system, and imported the patch Chris mentioned above. The package I built from 
that has been stable for several days now.

Please find my diff attached. I hope the maintainer can import it into Bullseye.

commit 77914836bb483673261377a737cfb8f72efff81c
Author: Peter van Dijk <pe...@7bits.nl>
Date:   Wed Jan 5 13:51:23 2022 +0100

    import upstream patch to fix Evolution crashes

diff --git a/debian/changelog b/debian/changelog
index 0a21d5f..e60e774 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+evolution-data-server (3.38.3-1.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Import https://gitlab.gnome.org/GNOME/evolution-data-server/-/commit/1f1017492
+    to fix https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=986564
+
+ -- Peter van Dijk <pe...@7bits.nl>  Wed, 05 Jan 2022 13:49:49 +0100
+
 evolution-data-server (3.38.3-1) unstable; urgency=medium
 
   * New upstream release
diff --git a/debian/libcamel-1.2-62.symbols b/debian/libcamel-1.2-62.symbols
index 467511e..0cf7260 100644
--- a/debian/libcamel-1.2-62.symbols
+++ b/debian/libcamel-1.2-62.symbols
@@ -1359,6 +1359,8 @@ libcamel-1.2.so.62 libcamel-1.2-62 #MINVER#
  camel_util_bdata_get_string@Base 3.24.1
  camel_util_bdata_put_number@Base 3.24.1
  camel_util_bdata_put_string@Base 3.24.1
+ camel_utils_weak_ref_free@Base 3.38.3-1.1
+ camel_utils_weak_ref_new@Base 3.38.3-1.1
  camel_uudecode_step@Base 3.19.92
  camel_uuencode_close@Base 3.19.92
  camel_uuencode_step@Base 3.19.92
diff --git a/debian/patches/evolution-crash.patch b/debian/patches/evolution-crash.patch
new file mode 100644
index 0000000..0270049
--- /dev/null
+++ b/debian/patches/evolution-crash.patch
@@ -0,0 +1,253 @@
+import https://gitlab.gnome.org/GNOME/evolution-data-server/-/commit/1f1017492
+
+this fixes https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=986564
+--- a/src/camel/camel-folder.c
++++ b/src/camel/camel-folder.c
+@@ -152,50 +152,61 @@
+ 	camel_folder_synchronize_sync (folder, FALSE, cancellable, error);
+ }
+ 
++static void
++folder_schedule_store_changes_job (CamelFolder *folder)
++{
++	CamelSession *session;
++	CamelStore *parent_store;
++
++	g_return_if_fail (CAMEL_IS_FOLDER (folder));
++
++	parent_store = camel_folder_get_parent_store (folder);
++	session = parent_store ? camel_service_ref_session (CAMEL_SERVICE (parent_store)) : NULL;
++	if (session) {
++		gchar *description;
++
++		/* Translators: The first “%s” is replaced with an account name and the second “%s”
++		   is replaced with a full path name. The spaces around “:” are intentional, as
++		   the whole “%s : %s” is meant as an absolute identification of the folder. */
++		description = g_strdup_printf (_("Storing changes in folder “%s : %s”"),
++			camel_service_get_display_name (CAMEL_SERVICE (parent_store)),
++			camel_folder_get_full_name (folder));
++
++		camel_session_submit_job (session, description,
++			folder_store_changes_job_cb,
++			g_object_ref (folder), g_object_unref);
++
++		g_free (description);
++	}
++
++	g_clear_object (&session);
++}
++
+ static gboolean
+-folder_schedule_store_changes_job (gpointer user_data)
++folder_schedule_store_changes_job_cb (gpointer user_data)
+ {
+-	CamelFolder *folder = user_data;
++	GWeakRef *weak_ref = user_data;
+ 	GSource *source;
++	CamelFolder *folder;
+ 
+ 	source = g_main_current_source ();
+ 
+ 	if (g_source_is_destroyed (source))
+ 		return FALSE;
+ 
+-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+-
+-	g_mutex_lock (&folder->priv->store_changes_lock);
+-
+-	if (folder->priv->store_changes_id == g_source_get_id (source)) {
+-		CamelSession *session;
+-		CamelStore *parent_store;
+-
+-		folder->priv->store_changes_id = 0;
+-
+-		parent_store = camel_folder_get_parent_store (folder);
+-		session = parent_store ? camel_service_ref_session (CAMEL_SERVICE (parent_store)) : NULL;
+-		if (session) {
+-			gchar *description;
++	folder = g_weak_ref_get (weak_ref);
++	if (folder) {
++		g_mutex_lock (&folder->priv->store_changes_lock);
+ 
+-			/* Translators: The first “%s” is replaced with an account name and the second “%s”
+-			   is replaced with a full path name. The spaces around “:” are intentional, as
+-			   the whole “%s : %s” is meant as an absolute identification of the folder. */
+-			description = g_strdup_printf (_("Storing changes in folder “%s : %s”"),
+-				camel_service_get_display_name (CAMEL_SERVICE (parent_store)),
+-				camel_folder_get_full_name (folder));
+-
+-			camel_session_submit_job (session, description,
+-				folder_store_changes_job_cb,
+-				g_object_ref (folder), g_object_unref);
+-
+-			g_free (description);
++		if (folder->priv->store_changes_id == g_source_get_id (source)) {
++			folder->priv->store_changes_id = 0;
++			folder_schedule_store_changes_job (folder);
+ 		}
+ 
+-		g_clear_object (&session);
+-	}
++		g_mutex_unlock (&folder->priv->store_changes_lock);
+ 
+-	g_mutex_unlock (&folder->priv->store_changes_lock);
++		g_object_unref (folder);
++	}
+ 
+ 	return FALSE;
+ }
+@@ -235,8 +246,9 @@
+ 		if (interval == 0)
+ 			folder_schedule_store_changes_job (folder);
+ 		else if (interval > 0)
+-			folder->priv->store_changes_id = g_timeout_add_seconds (interval,
+-				folder_schedule_store_changes_job, folder);
++			folder->priv->store_changes_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, interval,
++				folder_schedule_store_changes_job_cb,
++				camel_utils_weak_ref_new (folder), (GDestroyNotify) camel_utils_weak_ref_free);
+ 	}
+ 
+ 	g_mutex_unlock (&folder->priv->store_changes_lock);
+@@ -788,6 +800,12 @@
+ 
+ 	folder = CAMEL_FOLDER (object);
+ 
++	g_mutex_lock (&folder->priv->store_changes_lock);
++	if (folder->priv->store_changes_id)
++		g_source_remove (folder->priv->store_changes_id);
++	folder->priv->store_changes_id = 0;
++	g_mutex_unlock (&folder->priv->store_changes_lock);
++
+ 	if (folder->priv->summary) {
+ 		camel_folder_summary_save (folder->priv->summary, NULL);
+ 		g_clear_object (&folder->priv->summary);
+@@ -800,12 +818,6 @@
+ 		folder->priv->parent_store = NULL;
+ 	}
+ 
+-	g_mutex_lock (&folder->priv->store_changes_lock);
+-	if (folder->priv->store_changes_id)
+-		g_source_remove (folder->priv->store_changes_id);
+-	folder->priv->store_changes_id = 0;
+-	g_mutex_unlock (&folder->priv->store_changes_lock);
+-
+ 	/* Chain up to parent's dispose () method. */
+ 	G_OBJECT_CLASS (camel_folder_parent_class)->dispose (object);
+ }
+--- a/src/camel/camel-utils.c
++++ b/src/camel/camel-utils.c
+@@ -240,3 +240,47 @@
+ 
+ 	return mktime (&tm);
+ }
++
++/**
++ * camel_utils_weak_ref_new: (skip)
++ * @object: (nullable): a #GObject or %NULL
++ *
++ * Allocates a new #GWeakRef and calls g_weak_ref_set() with @object.
++ *
++ * Free the returned #GWeakRef with camel_utils_weak_ref_free().
++ *
++ * Returns: (transfer full): a new #GWeakRef
++ *
++ * Since: 3.38.4
++ **/
++GWeakRef *
++camel_utils_weak_ref_new (gpointer object)
++{
++	GWeakRef *weak_ref;
++
++	/* Based on e_weak_ref_new(). */
++
++	weak_ref = g_slice_new0 (GWeakRef);
++	g_weak_ref_init (weak_ref, object);
++
++	return weak_ref;
++}
++
++/**
++ * camel_utils_weak_ref_free: (skip)
++ * @weak_ref: a #GWeakRef
++ *
++ * Frees a #GWeakRef created by camel_utils_weak_ref_new().
++ *
++ * Since: 3.38.4
++ **/
++void
++camel_utils_weak_ref_free (GWeakRef *weak_ref)
++{
++	g_return_if_fail (weak_ref != NULL);
++
++	/* Based on e_weak_ref_free(). */
++
++	g_weak_ref_clear (weak_ref);
++	g_slice_free (GWeakRef, weak_ref);
++}
+--- a/src/camel/camel-utils.h
++++ b/src/camel/camel-utils.h
+@@ -41,6 +41,9 @@
+ 						 CamelTimeUnit unit,
+ 						 gint value);
+ 
++GWeakRef *	camel_utils_weak_ref_new	(gpointer object);
++void		camel_utils_weak_ref_free	(GWeakRef *weak_ref);
++
+ G_END_DECLS
+ 
+ #endif /* CAMEL_UTILS_H */
+--- a/src/camel/providers/imapx/camel-imapx-server.c
++++ b/src/camel/providers/imapx/camel-imapx-server.c
+@@ -380,32 +380,6 @@
+ 	}
+ }
+ 
+-static GWeakRef *
+-imapx_weak_ref_new (gpointer object)
+-{
+-	GWeakRef *weak_ref;
+-
+-	/* XXX Might want to expose this in Camel's public API if it
+-	 *     proves useful elsewhere.  Based on e_weak_ref_new(). */
+-
+-	weak_ref = g_slice_new0 (GWeakRef);
+-	g_weak_ref_init (weak_ref, object);
+-
+-	return weak_ref;
+-}
+-
+-static void
+-imapx_weak_ref_free (GWeakRef *weak_ref)
+-{
+-	g_return_if_fail (weak_ref != NULL);
+-
+-	/* XXX Might want to expose this in Camel's public API if it
+-	 *     proves useful elsewhere.  Based on e_weak_ref_free(). */
+-
+-	g_weak_ref_clear (weak_ref);
+-	g_slice_free (GWeakRef, weak_ref);
+-}
+-
+ static const CamelIMAPXUntaggedRespHandlerDesc *
+ replace_untagged_descriptor (GHashTable *untagged_handlers,
+                              const gchar *key,
+@@ -700,8 +674,8 @@
+ 	g_source_set_callback (
+ 		is->priv->inactivity_timeout,
+ 		imapx_server_inactivity_timeout_cb,
+-		imapx_weak_ref_new (is),
+-		(GDestroyNotify) imapx_weak_ref_free);
++		camel_utils_weak_ref_new (is),
++		(GDestroyNotify) camel_utils_weak_ref_free);
+ 	g_source_attach (is->priv->inactivity_timeout, NULL);
+ 
+ 	g_mutex_unlock (&is->priv->inactivity_timeout_lock);
+@@ -7207,7 +7181,7 @@
+ 	is->priv->idle_pending = g_timeout_source_new_seconds (IMAPX_IDLE_WAIT_SECONDS);
+ 	g_source_set_callback (
+ 		is->priv->idle_pending, imapx_server_run_idle_thread_cb,
+-		imapx_weak_ref_new (is), (GDestroyNotify) imapx_weak_ref_free);
++		camel_utils_weak_ref_new (is), (GDestroyNotify) camel_utils_weak_ref_free);
+ 	g_source_attach (is->priv->idle_pending, NULL);
+ 
+ 	g_mutex_unlock (&is->priv->idle_lock);
diff --git a/debian/patches/series b/debian/patches/series
index d876186..22f8341 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,3 +3,4 @@ ubuntu_gettext_domain.patch
 I-281-GLibTools.cmake-Use-basename-in-glib-mkenums-templa.patch
 M-62-GObjectIntrospection.cmake-Specify-the-sources-top-d.patch
 I-282-tests-Avoid-build-source-directories-in-executables.patch
+evolution-crash.patch

Reply via email to