From d901e4c8a6241d7322ba71546fa5d826a5479b57 Mon Sep 17 00:00:00 2001 From: Evangelos Ribeiro Tzaras Date: Sun, 22 Jan 2023 14:49:35 +0100 Subject: [PATCH] application: Delay shutting down until database is done Operations on the database are not cancellable, so we need to ensure any critical code (such as database migration) has completed. Otherwise we risk leaving the database in a locked state (or worse): WARNING **: 09:24:53.428: Failed to determine schema version: sqlite3_prepare_v2 failed: database is locked: CREATE TABLE IF NOT EXISTS _gom_version (version INTEGER); --- src/calls-application.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/calls-application.c b/src/calls-application.c index 07dac28..2f47c6e 100644 --- a/src/calls-application.c +++ b/src/calls-application.c @@ -73,6 +73,7 @@ struct _CallsApplication { guint id_sigterm; guint id_sigint; gboolean shutdown; + gboolean db_done; }; G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION); @@ -566,7 +567,18 @@ calls_application_command_line (GApplication *application, static void app_shutdown (GApplication *application) { - quit_calls (CALLS_APPLICATION (application)); + g_autoptr (GTimer) timer = g_timer_new (); + CallsApplication *self = CALLS_APPLICATION (application); + GMainContext *context = g_main_context_default (); + + quit_calls (self); + + while (self->record_store && !self->db_done) { + if (g_timer_elapsed (timer, NULL) > 10) + break; + + g_main_context_iteration (context, TRUE); + } cui_uninit (); @@ -590,6 +602,22 @@ notify_window_visible_cb (GtkWidget *window, } +static void +on_db_done (CallsRecordStore *store, + gboolean success, + CallsApplication *self) +{ + g_assert (CALLS_IS_APPLICATION (self)); + + self->db_done = TRUE; + g_debug ("Database opened %ssuccesfully", + success ? "" : "un"); + + if (!success) + g_warning ("Database did not get opened"); +} + + static void start_proper (CallsApplication *self) { @@ -607,6 +635,10 @@ start_proper (CallsApplication *self) self->record_store = calls_record_store_new (); g_assert (self->record_store != NULL); + g_signal_connect (self->record_store, "db-done", + G_CALLBACK (on_db_done), + self); + self->notifier = calls_notifier_new (); g_assert (CALLS_IS_NOTIFIER (self->notifier));