1From 1fc6a5c9b6a2b620ac4370d64c558f9b33aff063 Mon Sep 17 00:00:00 2001 2From: Philip Withnall <pwithnall@endlessos.org> 3Date: Mon, 30 May 2022 17:55:43 +0100 4Subject: [PATCH 3/3] tests: Add a test for GFileMonitor deadlocks 5MIME-Version: 1.0 6Content-Type: text/plain; charset=UTF-8 7Content-Transfer-Encoding: 8bit 8 9This test is opportunistic in that it’s not possible to detect whether 10the race condition has been hit (other than by hitting a deadlock). 11 12So the only approach we can take for testing is to loop over the code 13which has previously been known to cause a deadlock a number of times. 14 15The number of repetitions is chosen from running the test with the 16deadlock fix reverted. 17 18Signed-off-by: Philip Withnall <pwithnall@endlessos.org> 19 20Helps: #1941 21--- 22 gio/tests/testfilemonitor.c | 52 +++++++++++++++++++++++++++++++++++++ 23 1 file changed, 52 insertions(+) 24 25diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c 26index a47aeab38..082f0db26 100644 27--- a/gio/tests/testfilemonitor.c 28+++ b/gio/tests/testfilemonitor.c 29@@ -1036,6 +1036,57 @@ test_file_hard_links (Fixture *fixture, 30 g_object_unref (data.output_stream); 31 } 32 33+static void 34+test_finalize_in_callback (Fixture *fixture, 35+ gconstpointer user_data) 36+{ 37+ GFile *file = NULL; 38+ guint i; 39+ 40+ g_test_summary ("Test that finalization of a GFileMonitor in one of its " 41+ "callbacks doesn’t cause a deadlock."); 42+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/1941"); 43+ 44+ file = g_file_get_child (fixture->tmp_dir, "race-file"); 45+ 46+ for (i = 0; i < 50; i++) 47+ { 48+ GFileMonitor *monitor = NULL; 49+ GError *local_error = NULL; 50+ 51+ /* Monitor the file. */ 52+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &local_error); 53+ g_assert_no_error (local_error); 54+ g_assert_nonnull (monitor); 55+ 56+ /* Create the file. */ 57+ g_file_replace_contents (file, "hello", 5, NULL, FALSE, 58+ G_FILE_CREATE_NONE, NULL, NULL, &local_error); 59+ g_assert_no_error (local_error); 60+ 61+ /* Immediately drop the last ref to the monitor in the hope that this 62+ * happens in the middle of the critical section in 63+ * g_file_monitor_source_handle_event(), so that any cleanup at the end 64+ * of that function is done with a now-finalised file monitor. */ 65+ g_object_unref (monitor); 66+ 67+ /* Re-create the monitor and do the same again for deleting the file, to 68+ * give a second chance at hitting the race condition. */ 69+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &local_error); 70+ g_assert_no_error (local_error); 71+ g_assert_nonnull (monitor); 72+ 73+ /* Delete the file. */ 74+ g_file_delete (file, NULL, &local_error); 75+ g_assert_no_error (local_error); 76+ 77+ /* Drop the ref again. */ 78+ g_object_unref (monitor); 79+ } 80+ 81+ g_object_unref (file); 82+} 83+ 84 int 85 main (int argc, char *argv[]) 86 { 87@@ -1047,6 +1098,7 @@ main (int argc, char *argv[]) 88 g_test_add ("/monitor/dir-not-existent", Fixture, NULL, setup, test_dir_non_existent, teardown); 89 g_test_add ("/monitor/cross-dir-moves", Fixture, NULL, setup, test_cross_dir_moves, teardown); 90 g_test_add ("/monitor/file/hard-links", Fixture, NULL, setup, test_file_hard_links, teardown); 91+ g_test_add ("/monitor/finalize-in-callback", Fixture, NULL, setup, test_finalize_in_callback, teardown); 92 93 return g_test_run (); 94 } 95-- 962.41.0.windows.3 97 98