glib2/backport-tests-Add-a-test-for-GFileMonitor-deadlocks.patch
liningjie 70930634b7 glocalfilemonitor: Avoid file monitor destruction from event thread
(cherry picked from commit 54ebb050937636f3e8cb2db8a02ddb7d2f975b2e)
2023-10-09 10:17:27 +08:00

98 lines
3.4 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 1fc6a5c9b6a2b620ac4370d64c558f9b33aff063 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Mon, 30 May 2022 17:55:43 +0100
Subject: [PATCH 3/3] tests: Add a test for GFileMonitor deadlocks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This test is opportunistic in that its not possible to detect whether
the race condition has been hit (other than by hitting a deadlock).
So the only approach we can take for testing is to loop over the code
which has previously been known to cause a deadlock a number of times.
The number of repetitions is chosen from running the test with the
deadlock fix reverted.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1941
---
gio/tests/testfilemonitor.c | 52 +++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c
index a47aeab38..082f0db26 100644
--- a/gio/tests/testfilemonitor.c
+++ b/gio/tests/testfilemonitor.c
@@ -1036,6 +1036,57 @@ test_file_hard_links (Fixture *fixture,
g_object_unref (data.output_stream);
}
+static void
+test_finalize_in_callback (Fixture *fixture,
+ gconstpointer user_data)
+{
+ GFile *file = NULL;
+ guint i;
+
+ g_test_summary ("Test that finalization of a GFileMonitor in one of its "
+ "callbacks doesnt cause a deadlock.");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/1941");
+
+ file = g_file_get_child (fixture->tmp_dir, "race-file");
+
+ for (i = 0; i < 50; i++)
+ {
+ GFileMonitor *monitor = NULL;
+ GError *local_error = NULL;
+
+ /* Monitor the file. */
+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &local_error);
+ g_assert_no_error (local_error);
+ g_assert_nonnull (monitor);
+
+ /* Create the file. */
+ g_file_replace_contents (file, "hello", 5, NULL, FALSE,
+ G_FILE_CREATE_NONE, NULL, NULL, &local_error);
+ g_assert_no_error (local_error);
+
+ /* Immediately drop the last ref to the monitor in the hope that this
+ * happens in the middle of the critical section in
+ * g_file_monitor_source_handle_event(), so that any cleanup at the end
+ * of that function is done with a now-finalised file monitor. */
+ g_object_unref (monitor);
+
+ /* Re-create the monitor and do the same again for deleting the file, to
+ * give a second chance at hitting the race condition. */
+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &local_error);
+ g_assert_no_error (local_error);
+ g_assert_nonnull (monitor);
+
+ /* Delete the file. */
+ g_file_delete (file, NULL, &local_error);
+ g_assert_no_error (local_error);
+
+ /* Drop the ref again. */
+ g_object_unref (monitor);
+ }
+
+ g_object_unref (file);
+}
+
int
main (int argc, char *argv[])
{
@@ -1047,6 +1098,7 @@ main (int argc, char *argv[])
g_test_add ("/monitor/dir-not-existent", Fixture, NULL, setup, test_dir_non_existent, teardown);
g_test_add ("/monitor/cross-dir-moves", Fixture, NULL, setup, test_cross_dir_moves, teardown);
g_test_add ("/monitor/file/hard-links", Fixture, NULL, setup, test_file_hard_links, teardown);
+ g_test_add ("/monitor/finalize-in-callback", Fixture, NULL, setup, test_finalize_in_callback, teardown);
return g_test_run ();
}
--
2.41.0.windows.3