From aea374710e8f3c61ad652a783162829fa87669e2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 9 Feb 2019 21:40:19 +0000 Subject: [PATCH] daemon: Time out client txn connections after 30s This removes the "transaction monitor". Originally the idea here was things would queue, but we never really made that work. Since transactions started grabbing the libostree sysroot lock in particular. Rip out the transaction monitor code with the queue and have a singleton txn ref in the sysroot object. This should ensure that if a txn is active, one always gets an error message about which one. Next, add a 30s timeout for connections to the transaction DBus sockets after they're complete. This should address https://github.com/projectatomic/rpm-ostree/issues/1692 which is a case where gnome-software was leaking the txn DBus connection and keeping it alive. Closes: #1755 Approved by: cgwalters --- Makefile-daemon.am | 2 - src/daemon/rpmostreed-os-experimental.c | 38 +--- src/daemon/rpmostreed-os-experimental.h | 3 +- src/daemon/rpmostreed-os.c | 127 ++++++----- src/daemon/rpmostreed-os.h | 3 +- src/daemon/rpmostreed-sysroot.c | 224 +++++++++++--------- src/daemon/rpmostreed-sysroot.h | 13 ++ src/daemon/rpmostreed-transaction-monitor.c | 204 ------------------ src/daemon/rpmostreed-transaction-monitor.h | 35 --- src/daemon/rpmostreed-transaction.c | 47 +++- src/daemon/rpmostreed-transaction.h | 1 + src/daemon/rpmostreed-types.h | 3 - 12 files changed, 243 insertions(+), 457 deletions(-) delete mode 100644 src/daemon/rpmostreed-transaction-monitor.c delete mode 100644 src/daemon/rpmostreed-transaction-monitor.h diff --git a/Makefile-daemon.am b/Makefile-daemon.am index abe046d7..96b76d09 100644 --- a/Makefile-daemon.am +++ b/Makefile-daemon.am @@ -40,8 +40,6 @@ librpmostreed_la_SOURCES = \ src/daemon/rpmostreed-deployment-utils.c \ src/daemon/rpmostreed-transaction.h \ src/daemon/rpmostreed-transaction.c \ - src/daemon/rpmostreed-transaction-monitor.h \ - src/daemon/rpmostreed-transaction-monitor.c \ src/daemon/rpmostreed-transaction-types.h \ src/daemon/rpmostreed-transaction-types.c \ src/daemon/rpmostreed-transaction-livefs.c \ diff --git a/src/daemon/rpmostreed-os-experimental.c b/src/daemon/rpmostreed-os-experimental.c index 52fa8877..608369fa 100644 --- a/src/daemon/rpmostreed-os-experimental.c +++ b/src/daemon/rpmostreed-os-experimental.c @@ -31,7 +31,6 @@ #include "rpmostreed-utils.h" #include "rpmostree-util.h" #include "rpmostreed-transaction.h" -#include "rpmostreed-transaction-monitor.h" #include "rpmostreed-transaction-types.h" typedef struct _RpmostreedOSExperimentalClass RpmostreedOSExperimentalClass; @@ -39,7 +38,6 @@ typedef struct _RpmostreedOSExperimentalClass RpmostreedOSExperimentalClass; struct _RpmostreedOSExperimental { RPMOSTreeOSSkeleton parent_instance; - RpmostreedTransactionMonitor *transaction_monitor; }; struct _RpmostreedOSExperimentalClass @@ -57,23 +55,6 @@ G_DEFINE_TYPE_WITH_CODE (RpmostreedOSExperimental, rpmostreed_osexperimental_iface_init) ); -static RpmostreedTransaction * -merge_compatible_txn (RpmostreedOSExperimental *self, - GDBusMethodInvocation *invocation) -{ - glnx_unref_object RpmostreedTransaction *transaction = NULL; - - /* If a compatible transaction is in progress, share its bus address. */ - transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor); - if (transaction != NULL) - { - if (rpmostreed_transaction_is_compatible (transaction, invocation)) - return g_steal_pointer (&transaction); - } - - return NULL; -} - /* ---------------------------------------------------------------------------------------------------- */ static void @@ -89,8 +70,6 @@ os_dispose (GObject *object) object_path, object); } - g_clear_object (&self->transaction_monitor); - G_OBJECT_CLASS (rpmostreed_osexperimental_parent_class)->dispose (object); } @@ -159,13 +138,15 @@ osexperimental_handle_live_fs (RPMOSTreeOSExperimental *interface, GDBusMethodInvocation *invocation, GVariant *arg_options) { - RpmostreedOSExperimental *self = RPMOSTREED_OSEXPERIMENTAL (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -184,7 +165,7 @@ osexperimental_handle_live_fs (RPMOSTreeOSExperimental *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -213,23 +194,18 @@ rpmostreed_osexperimental_iface_init (RPMOSTreeOSExperimentalIface *iface) RPMOSTreeOSExperimental * rpmostreed_osexperimental_new (OstreeSysroot *sysroot, OstreeRepo *repo, - const char *name, - RpmostreedTransactionMonitor *monitor) + const char *name) { RpmostreedOSExperimental *obj = NULL; g_autofree char *path = NULL; g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL); g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (RPMOSTREED_IS_TRANSACTION_MONITOR (monitor), NULL); path = rpmostreed_generate_object_path (BASE_DBUS_PATH, name, NULL); obj = g_object_new (RPMOSTREED_TYPE_OSEXPERIMENTAL, NULL); - /* FIXME Make this a construct-only property? */ - obj->transaction_monitor = g_object_ref (monitor); - rpmostreed_daemon_publish (rpmostreed_daemon_get (), path, FALSE, obj); return RPMOSTREE_OSEXPERIMENTAL (obj); diff --git a/src/daemon/rpmostreed-os-experimental.h b/src/daemon/rpmostreed-os-experimental.h index b3cfc0fa..29d19530 100644 --- a/src/daemon/rpmostreed-os-experimental.h +++ b/src/daemon/rpmostreed-os-experimental.h @@ -27,5 +27,4 @@ GType rpmostreed_osexperimental_get_type (void) G_GNUC_CONST; RPMOSTreeOSExperimental * rpmostreed_osexperimental_new (OstreeSysroot *sysroot, OstreeRepo *repo, - const char *name, - RpmostreedTransactionMonitor *monitor); + const char *name); diff --git a/src/daemon/rpmostreed-os.c b/src/daemon/rpmostreed-os.c index a8468f18..9da37328 100644 --- a/src/daemon/rpmostreed-os.c +++ b/src/daemon/rpmostreed-os.c @@ -34,7 +34,6 @@ #include "rpmostreed-utils.h" #include "rpmostree-util.h" #include "rpmostreed-transaction.h" -#include "rpmostreed-transaction-monitor.h" #include "rpmostreed-transaction-types.h" typedef struct _RpmostreedOSClass RpmostreedOSClass; @@ -42,7 +41,6 @@ typedef struct _RpmostreedOSClass RpmostreedOSClass; struct _RpmostreedOS { RPMOSTreeOSSkeleton parent_instance; - RpmostreedTransactionMonitor *transaction_monitor; gboolean on_session_bus; guint signal_id; }; @@ -260,8 +258,6 @@ os_dispose (GObject *object) object_path, object); } - g_clear_object (&self->transaction_monitor); - if (self->signal_id > 0) g_signal_handler_disconnect (rpmostreed_sysroot_get (), self->signal_id); @@ -448,23 +444,6 @@ out: return TRUE; } -static RpmostreedTransaction * -merge_compatible_txn (RpmostreedOS *self, - GDBusMethodInvocation *invocation) -{ - glnx_unref_object RpmostreedTransaction *transaction = NULL; - - /* If a compatible transaction is in progress, share its bus address. */ - transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor); - if (transaction != NULL) - { - if (rpmostreed_transaction_is_compatible (transaction, invocation)) - return g_steal_pointer (&transaction); - } - - return NULL; -} - static gboolean refresh_cached_update (RpmostreedOS*, GError **error); @@ -484,13 +463,16 @@ os_handle_download_update_rpm_diff (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation) { RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); const char *osname; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -514,13 +496,13 @@ os_handle_download_update_rpm_diff (RPMOSTreeOS *interface, if (transaction == NULL) goto out; + rpmostreed_sysroot_set_txn (rsysroot, transaction); + /* Make sure we refresh CachedUpdate after the transaction. This normally happens * automatically if new data was downloaded (through the repo mtime bump --> UPDATED * signal), but we also want to do this even if the data was already present. */ g_signal_connect (transaction, "closed", G_CALLBACK (on_auto_update_done), self); - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); - out: if (local_error != NULL) { @@ -576,9 +558,11 @@ os_merge_or_start_deployment_txn (RPMOSTreeOS *interface, g_autoptr(GError) local_error = NULL; /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto err; - glnx_unref_object RpmostreedTransaction *transaction = - merge_compatible_txn (self, invocation); if (!transaction) { glnx_unref_object OstreeSysroot *ot_sysroot = NULL; @@ -594,7 +578,7 @@ os_merge_or_start_deployment_txn (RPMOSTreeOS *interface, if (!transaction) goto err; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); /* For the AutomaticUpdateTrigger "check" case, we want to make sure we refresh * the CachedUpdate property; "stage" will do this through sysroot_changed */ @@ -815,8 +799,6 @@ os_handle_rollback (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, GVariant *arg_options) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); const char *osname; @@ -824,7 +806,11 @@ os_handle_rollback (RPMOSTreeOS *interface, GVariantDict options_dict; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -855,7 +841,7 @@ os_handle_rollback (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -877,8 +863,6 @@ os_handle_refresh_md (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, GVariant *arg_options) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); const char *osname; @@ -886,7 +870,11 @@ os_handle_refresh_md (RPMOSTreeOS *interface, RpmOstreeTransactionRefreshMdFlags flags = 0; g_auto(GVariantDict) dict; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -912,7 +900,7 @@ os_handle_refresh_md (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -934,15 +922,17 @@ os_handle_clear_rollback_target (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, GVariant *arg_options) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); RpmOstreeTransactionCleanupFlags flags = 0; const char *osname; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -963,7 +953,7 @@ os_handle_clear_rollback_target (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -986,8 +976,6 @@ os_handle_set_initramfs_state (RPMOSTreeOS *interface, const char *const*args, GVariant *arg_options) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); g_autoptr(GVariantDict) dict = NULL; @@ -995,7 +983,11 @@ os_handle_set_initramfs_state (RPMOSTreeOS *interface, gboolean reboot = FALSE; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -1022,7 +1014,7 @@ os_handle_set_initramfs_state (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -1060,13 +1052,15 @@ os_handle_kernel_args (RPMOSTreeOS *interface, const char * const *kernel_args_deleted, GVariant *arg_options) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -1091,7 +1085,7 @@ os_handle_kernel_args (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -1195,15 +1189,17 @@ os_handle_cleanup (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, const char *const*args) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); RpmOstreeTransactionCleanupFlags flags = 0; const char *osname; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -1245,7 +1241,7 @@ os_handle_cleanup (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -1338,14 +1334,16 @@ os_handle_download_rebase_rpm_diff (RPMOSTreeOS *interface, const char * const *arg_packages) { /* TODO: Totally ignoring arg_packages for now */ - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); const char *osname; GError *local_error = NULL; - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -1369,7 +1367,7 @@ os_handle_download_rebase_rpm_diff (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -1475,8 +1473,6 @@ os_handle_download_deploy_rpm_diff (RPMOSTreeOS *interface, const char *arg_revision, const char * const *arg_packages) { - RpmostreedOS *self = RPMOSTREED_OS (interface); - glnx_unref_object RpmostreedTransaction *transaction = NULL; glnx_unref_object OstreeSysroot *ot_sysroot = NULL; g_autoptr(GCancellable) cancellable = g_cancellable_new (); const char *osname; @@ -1484,7 +1480,11 @@ os_handle_download_deploy_rpm_diff (RPMOSTreeOS *interface, /* XXX Ignoring arg_packages for now. */ - transaction = merge_compatible_txn (self, invocation); + /* try to merge with an existing transaction, otherwise start a new one */ + glnx_unref_object RpmostreedTransaction *transaction = NULL; + RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get (); + if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error)) + goto out; if (transaction) goto out; @@ -1507,7 +1507,7 @@ os_handle_download_deploy_rpm_diff (RPMOSTreeOS *interface, if (transaction == NULL) goto out; - rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction); + rpmostreed_sysroot_set_txn (rsysroot, transaction); out: if (local_error != NULL) @@ -1693,23 +1693,18 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface) RPMOSTreeOS * rpmostreed_os_new (OstreeSysroot *sysroot, OstreeRepo *repo, - const char *name, - RpmostreedTransactionMonitor *monitor) + const char *name) { RpmostreedOS *obj = NULL; g_autofree char *path = NULL; g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL); g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (RPMOSTREED_IS_TRANSACTION_MONITOR (monitor), NULL); path = rpmostreed_generate_object_path (BASE_DBUS_PATH, name, NULL); obj = g_object_new (RPMOSTREED_TYPE_OS, "name", name, NULL); - /* FIXME Make this a construct-only property? */ - obj->transaction_monitor = g_object_ref (monitor); - /* FIXME - use GInitable */ { g_autoptr(GError) local_error = NULL; if (!rpmostreed_os_load_internals (obj, &local_error)) diff --git a/src/daemon/rpmostreed-os.h b/src/daemon/rpmostreed-os.h index c5106584..466ad133 100644 --- a/src/daemon/rpmostreed-os.h +++ b/src/daemon/rpmostreed-os.h @@ -30,5 +30,4 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(RpmOstreeUpdateDeploymentModifiers, g_variant_unre GType rpmostreed_os_get_type (void) G_GNUC_CONST; RPMOSTreeOS * rpmostreed_os_new (OstreeSysroot *sysroot, OstreeRepo *repo, - const char *name, - RpmostreedTransactionMonitor *monitor); + const char *name); diff --git a/src/daemon/rpmostreed-sysroot.c b/src/daemon/rpmostreed-sysroot.c index 0bdf269c..ea15afdd 100644 --- a/src/daemon/rpmostreed-sysroot.c +++ b/src/daemon/rpmostreed-sysroot.c @@ -28,7 +28,6 @@ #include "rpmostreed-deployment-utils.h" #include "rpmostreed-errors.h" #include "rpmostreed-transaction.h" -#include "rpmostreed-transaction-monitor.h" #include "rpmostree-output.h" @@ -39,6 +38,9 @@ #include #include +/* Avoid clients leaking their bus connections keeping the transaction open */ +#define FORCE_CLOSE_TXN_TIMEOUT_SECS 30 + static gboolean sysroot_reload_ostree_configs_and_deployments (RpmostreedSysroot *self, gboolean *out_changed, @@ -66,7 +68,8 @@ struct _RpmostreedSysroot { OstreeSysroot *ot_sysroot; OstreeRepo *repo; struct stat repo_last_stat; - RpmostreedTransactionMonitor *transaction_monitor; + RpmostreedTransaction *transaction; + guint close_transaction_timeout_id; PolkitAuthority *authority; gboolean on_session_bus; @@ -103,7 +106,6 @@ static void sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) { RpmostreedSysroot *self = RPMOSTREED_SYSROOT (opaque); - glnx_unref_object RpmostreedTransaction *transaction = NULL; gboolean output_to_self = FALSE; // The API previously passed these each time, but now we retain them as @@ -112,22 +114,20 @@ sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) static bool progress_state_percent; static guint progress_state_n_items; - transaction = - rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor); - if (transaction) - g_object_get (transaction, "output-to-self", &output_to_self, NULL); + if (self->transaction) + g_object_get (self->transaction, "output-to-self", &output_to_self, NULL); - if (!transaction || output_to_self) + if (!self->transaction || output_to_self) { rpmostree_output_default_handler (type, data, opaque); return; } + RPMOSTreeTransaction *transaction = RPMOSTREE_TRANSACTION (self->transaction); switch (type) { case RPMOSTREE_OUTPUT_MESSAGE: - rpmostree_transaction_emit_message (RPMOSTREE_TRANSACTION (transaction), - ((RpmOstreeOutputMessage*)data)->text); + rpmostree_transaction_emit_message (transaction, ((RpmOstreeOutputMessage*)data)->text); break; case RPMOSTREE_OUTPUT_PROGRESS_BEGIN: { @@ -138,8 +138,7 @@ sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) if (begin->percent) { progress_str = g_strdup (begin->prefix); - rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction), - progress_str, 0); + rpmostree_transaction_emit_percent_progress (transaction, progress_str, 0); progress_state_percent = true; } else if (begin->n > 0) @@ -147,13 +146,11 @@ sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) progress_str = g_strdup (begin->prefix); progress_state_n_items = begin->n; /* For backcompat, this is a percentage. See below */ - rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction), - progress_str, 0); + rpmostree_transaction_emit_percent_progress (transaction, progress_str, 0); } else { - rpmostree_transaction_emit_task_begin (RPMOSTREE_TRANSACTION (transaction), - begin->prefix); + rpmostree_transaction_emit_task_begin (transaction, begin->prefix); } } break; @@ -169,11 +166,11 @@ sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) int percentage = (update->c == progress_state_n_items) ? 100 : (((double)(update->c)) / (progress_state_n_items) * 100); g_autofree char *newtext = g_strdup_printf ("%s (%u/%u)", progress_str, update->c, progress_state_n_items); - rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction), newtext, percentage); + rpmostree_transaction_emit_percent_progress (transaction, newtext, percentage); } else { - rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction), progress_str, update->c); + rpmostree_transaction_emit_percent_progress (transaction, progress_str, update->c); } } break; @@ -186,11 +183,11 @@ sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) { if (progress_state_percent || progress_state_n_items > 0) { - rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction)); + rpmostree_transaction_emit_progress_end (transaction); } else { - rpmostree_transaction_emit_task_end (RPMOSTREE_TRANSACTION (transaction), "done"); + rpmostree_transaction_emit_task_end (transaction, "done"); } } break; @@ -270,51 +267,6 @@ handle_get_os (RPMOSTreeSysroot *object, return TRUE; } -static gboolean -sysroot_transform_transaction_to_attrs (GBinding *binding, - const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - RpmostreedTransaction *transaction; - GVariant *variant; - const char *method_name = ""; - const char *path = ""; - const char *sender_name = ""; - - transaction = g_value_get_object (src_value); - - if (transaction != NULL) - { - GDBusMethodInvocation *invocation; - - invocation = rpmostreed_transaction_get_invocation (transaction); - method_name = g_dbus_method_invocation_get_method_name (invocation); - path = g_dbus_method_invocation_get_object_path (invocation); - sender_name = g_dbus_method_invocation_get_sender (invocation); - } - - variant = g_variant_new ("(sss)", method_name, sender_name, path); - - g_value_set_variant (dst_value, variant); - - return TRUE; -} - -static gboolean -sysroot_transform_transaction_to_address (GBinding *binding, - const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - RpmostreedTransaction *transaction = g_value_get_object (src_value); - const char *address = ""; - if (transaction != NULL) - address = rpmostreed_transaction_get_client_address (transaction); - g_value_set_string (dst_value, address); - return TRUE; -} - static gboolean sysroot_populate_deployments_unlocked (RpmostreedSysroot *self, gboolean *out_changed, @@ -386,13 +338,11 @@ sysroot_populate_deployments_unlocked (RpmostreedSysroot *self, if (!g_hash_table_contains (self->os_interfaces, deployment_os)) { RPMOSTreeOS *obj = rpmostreed_os_new (self->ot_sysroot, self->repo, - deployment_os, - self->transaction_monitor); + deployment_os); g_hash_table_insert (self->os_interfaces, g_strdup (deployment_os), obj); RPMOSTreeOSExperimental *eobj = rpmostreed_osexperimental_new (self->ot_sysroot, self->repo, - deployment_os, - self->transaction_monitor); + deployment_os); g_hash_table_insert (self->osexperimental_interfaces, g_strdup (deployment_os), eobj); } @@ -569,7 +519,7 @@ sysroot_dispose (GObject *object) g_hash_table_remove_all (self->os_interfaces); g_hash_table_remove_all (self->osexperimental_interfaces); - g_clear_object (&self->transaction_monitor); + g_clear_object (&self->transaction); g_clear_object (&self->authority); G_OBJECT_CLASS (rpmostreed_sysroot_parent_class)->dispose (object); @@ -604,8 +554,6 @@ rpmostreed_sysroot_init (RpmostreedSysroot *self) self->monitor = NULL; - self->transaction_monitor = rpmostreed_transaction_monitor_new (); - if (g_getenv ("RPMOSTREE_USE_SESSION_BUS") != NULL) self->on_session_bus = TRUE; @@ -623,35 +571,6 @@ rpmostreed_sysroot_init (RpmostreedSysroot *self) rpmostree_output_set_callback (sysroot_output_cb, self); } -static void -sysroot_constructed (GObject *object) -{ - RpmostreedSysroot *self = RPMOSTREED_SYSROOT (object); - - g_object_bind_property_full (self->transaction_monitor, - "active-transaction", - self, - "active-transaction", - G_BINDING_DEFAULT | - G_BINDING_SYNC_CREATE, - sysroot_transform_transaction_to_attrs, - NULL, - NULL, - NULL); - g_object_bind_property_full (self->transaction_monitor, - "active-transaction", - self, - "active-transaction-path", - G_BINDING_DEFAULT | - G_BINDING_SYNC_CREATE, - sysroot_transform_transaction_to_address, - NULL, - NULL, - NULL); - - G_OBJECT_CLASS (rpmostreed_sysroot_parent_class)->constructed (object); -} - static gboolean sysroot_authorize_method (GDBusInterfaceSkeleton *interface, GDBusMethodInvocation *invocation) @@ -751,7 +670,6 @@ rpmostreed_sysroot_class_init (RpmostreedSysrootClass *klass) gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = sysroot_dispose; gobject_class->finalize = sysroot_finalize; - gobject_class->constructed = sysroot_constructed; signals[UPDATED] = g_signal_new ("updated", RPMOSTREED_TYPE_SYSROOT, @@ -903,6 +821,108 @@ rpmostreed_sysroot_load_state (RpmostreedSysroot *self, return TRUE; } +gboolean +rpmostreed_sysroot_prep_for_txn (RpmostreedSysroot *self, + GDBusMethodInvocation *invocation, + RpmostreedTransaction **out_compat_txn, + GError **error) +{ + if (self->transaction) + { + if (rpmostreed_transaction_is_compatible (self->transaction, invocation)) + { + *out_compat_txn = g_object_ref (self->transaction); + return TRUE; + } + const char *title = rpmostree_transaction_get_title ((RPMOSTreeTransaction*)(self->transaction)); + return glnx_throw (error, "Transaction in progress: %s", title); + } + *out_compat_txn = NULL; + return TRUE; +} + +gboolean +rpmostreed_sysroot_has_txn (RpmostreedSysroot *self) +{ + return self->transaction != NULL; +} + +static gboolean +on_force_close (gpointer data) +{ + RpmostreedSysroot *self = data; + + if (self->transaction) + { + rpmostreed_transaction_force_close (self->transaction); + rpmostreed_sysroot_set_txn (self, NULL); + } + + return FALSE; +} + +static void +on_txn_executed_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + RpmostreedSysroot *self = user_data; + gboolean executed; + g_object_get (object, "executed", &executed, NULL); + if (executed && self->close_transaction_timeout_id == 0) + { + self->close_transaction_timeout_id = + g_timeout_add_seconds (FORCE_CLOSE_TXN_TIMEOUT_SECS, on_force_close, self); + } +} + +void +rpmostreed_sysroot_set_txn (RpmostreedSysroot *self, + RpmostreedTransaction *txn) +{ + /* If the transaction is changing, clear the timer */ + if (self->close_transaction_timeout_id > 0) + { + g_source_remove (self->close_transaction_timeout_id); + self->close_transaction_timeout_id = 0; + } + + if (txn != NULL) + { + g_assert (self->transaction == NULL); + self->transaction = g_object_ref (txn); + + g_signal_connect (self->transaction, "notify::executed", + G_CALLBACK (on_txn_executed_changed), self); + + GDBusMethodInvocation *invocation = rpmostreed_transaction_get_invocation (self->transaction); + g_autoptr(GVariant) v = g_variant_ref_sink (g_variant_new ("(sss)", + g_dbus_method_invocation_get_method_name (invocation), + g_dbus_method_invocation_get_object_path (invocation), + g_dbus_method_invocation_get_sender (invocation))); + rpmostree_sysroot_set_active_transaction ((RPMOSTreeSysroot*)self, v); + rpmostree_sysroot_set_active_transaction_path ((RPMOSTreeSysroot*)self, + rpmostreed_transaction_get_client_address (self->transaction)); + } + else + { + g_assert (self->transaction); + g_clear_object (&self->transaction); + + g_autoptr(GVariant) v = g_variant_ref_sink (g_variant_new ("(sss)", "", "", "")); + rpmostree_sysroot_set_active_transaction ((RPMOSTreeSysroot *)self, v); + rpmostree_sysroot_set_active_transaction_path ((RPMOSTreeSysroot *)self, ""); + } +} + +void +rpmostreed_sysroot_finish_txn (RpmostreedSysroot *self, + RpmostreedTransaction *txn) +{ + g_assert (self->transaction == txn); + rpmostreed_sysroot_set_txn (self, NULL); +} + OstreeSysroot * rpmostreed_sysroot_get_root (RpmostreedSysroot *self) { diff --git a/src/daemon/rpmostreed-sysroot.h b/src/daemon/rpmostreed-sysroot.h index db6aa446..5841d511 100644 --- a/src/daemon/rpmostreed-sysroot.h +++ b/src/daemon/rpmostreed-sysroot.h @@ -49,4 +49,17 @@ gboolean rpmostreed_sysroot_load_state (RpmostreedSysroot *self OstreeRepo **out_repo, GError **error); +gboolean rpmostreed_sysroot_prep_for_txn (RpmostreedSysroot *self, + GDBusMethodInvocation *invocation, + RpmostreedTransaction **out_compat_txn, + GError **error); + +gboolean rpmostreed_sysroot_has_txn (RpmostreedSysroot *self); + +void rpmostreed_sysroot_finish_txn (RpmostreedSysroot *self, + RpmostreedTransaction *txn); + +void rpmostreed_sysroot_set_txn (RpmostreedSysroot *self, + RpmostreedTransaction *txn); + void rpmostreed_sysroot_emit_update (RpmostreedSysroot *self); diff --git a/src/daemon/rpmostreed-transaction-monitor.c b/src/daemon/rpmostreed-transaction-monitor.c deleted file mode 100644 index 165b9079..00000000 --- a/src/daemon/rpmostreed-transaction-monitor.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include "rpmostreed-transaction-monitor.h" - -#include - -#include "rpmostreed-transaction.h" - -typedef struct _RpmostreedTransactionMonitorClass RpmostreedTransactionMonitorClass; - -struct _RpmostreedTransactionMonitor { - GObjectClass parent; - - /* The head of the queue is the active transaction. */ - GQueue *transactions; -}; - -struct _RpmostreedTransactionMonitorClass { - GObjectClass parent_class; -}; - -enum { - PROP_0, - PROP_ACTIVE_TRANSACTION -}; - -G_DEFINE_TYPE (RpmostreedTransactionMonitor, - rpmostreed_transaction_monitor, - G_TYPE_OBJECT) - -static void -transaction_monitor_remove_transaction (RpmostreedTransactionMonitor *monitor, - RPMOSTreeTransaction *transaction) -{ - GList *link; - - link = g_queue_find (monitor->transactions, transaction); - - if (link != NULL) - { - GList *head; - gboolean need_notify; - - /* The head of the queue is the active transaction. */ - head = g_queue_peek_head_link (monitor->transactions); - need_notify = (link == head); - - g_object_unref (link->data); - g_queue_delete_link (monitor->transactions, link); - - if (need_notify) - { - /* Issue a notification so property bindings get updated. */ - g_object_notify (G_OBJECT (monitor), "active-transaction"); - } - } -} - -static void -transaction_monitor_notify_active_cb (RPMOSTreeTransaction *transaction, - GParamSpec *pspec, - RpmostreedTransactionMonitor *monitor) -{ - GList *head, *link; - - /* The head of the queue is the active transaction. */ - head = g_queue_peek_head_link (monitor->transactions); - link = g_queue_find (monitor->transactions, transaction); - - if (link == head) - { - /* Issue a notification so property bindings get updated. */ - g_object_notify (G_OBJECT (monitor), "active-transaction"); - } -} - -static void -transaction_monitor_closed_cb (RPMOSTreeTransaction *transaction, - RpmostreedTransactionMonitor *monitor) -{ - transaction_monitor_remove_transaction (monitor, transaction); -} - -static void -transaction_monitor_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - RpmostreedTransactionMonitor *monitor = RPMOSTREED_TRANSACTION_MONITOR (object); - gpointer v_object; - - switch (property_id) - { - case PROP_ACTIVE_TRANSACTION: - v_object = rpmostreed_transaction_monitor_ref_active_transaction (monitor); - g_value_take_object (value, v_object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -transaction_monitor_dispose (GObject *object) -{ - RpmostreedTransactionMonitor *monitor = RPMOSTREED_TRANSACTION_MONITOR (object); - - g_queue_free_full (monitor->transactions, (GDestroyNotify) g_object_unref); - - G_OBJECT_CLASS (rpmostreed_transaction_monitor_parent_class)->dispose (object); -} - -static void -rpmostreed_transaction_monitor_class_init (RpmostreedTransactionMonitorClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = transaction_monitor_get_property; - object_class->dispose = transaction_monitor_dispose; - - g_object_class_install_property (object_class, - PROP_ACTIVE_TRANSACTION, - g_param_spec_object ("active-transaction", - NULL, - NULL, - RPMOSTREED_TYPE_TRANSACTION, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); -} - -static void -rpmostreed_transaction_monitor_init (RpmostreedTransactionMonitor *monitor) -{ - monitor->transactions = g_queue_new (); -} - -RpmostreedTransactionMonitor * -rpmostreed_transaction_monitor_new (void) -{ - return g_object_new (RPMOSTREED_TYPE_TRANSACTION_MONITOR, NULL); -} - -void -rpmostreed_transaction_monitor_add (RpmostreedTransactionMonitor *monitor, - RpmostreedTransaction *transaction) -{ - g_return_if_fail (RPMOSTREED_IS_TRANSACTION_MONITOR (monitor)); - g_return_if_fail (RPMOSTREED_IS_TRANSACTION (transaction)); - - g_signal_connect_object (transaction, "notify::active", - G_CALLBACK (transaction_monitor_notify_active_cb), - monitor, 0); - - g_signal_connect_object (transaction, "closed", - G_CALLBACK (transaction_monitor_closed_cb), - monitor, 0); - - g_queue_push_head (monitor->transactions, g_object_ref (transaction)); - g_object_notify (G_OBJECT (monitor), "active-transaction"); -} - -RpmostreedTransaction * -rpmostreed_transaction_monitor_ref_active_transaction (RpmostreedTransactionMonitor *monitor) -{ - RpmostreedTransaction *transaction; - - g_return_val_if_fail (RPMOSTREED_IS_TRANSACTION_MONITOR (monitor), NULL); - - /* The head of the queue is the active transaction. */ - transaction = g_queue_peek_head (monitor->transactions); - - if (transaction != NULL) - { - /* An "inactive" transaction has completed its task - * and does not block other transactions from starting. */ - if (rpmostreed_transaction_get_active (transaction)) - g_object_ref (transaction); - else - transaction = NULL; - } - - return transaction; -} diff --git a/src/daemon/rpmostreed-transaction-monitor.h b/src/daemon/rpmostreed-transaction-monitor.h deleted file mode 100644 index 92f434f4..00000000 --- a/src/daemon/rpmostreed-transaction-monitor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "ostree.h" -#include "rpmostreed-types.h" - -#define RPMOSTREED_TYPE_TRANSACTION_MONITOR (rpmostreed_transaction_monitor_get_type ()) -#define RPMOSTREED_TRANSACTION_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RPMOSTREED_TYPE_TRANSACTION_MONITOR, RpmostreedTransactionMonitor)) -#define RPMOSTREED_IS_TRANSACTION_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), RPMOSTREED_TYPE_TRANSACTION_MONITOR)) - -GType rpmostreed_transaction_monitor_get_type (void) G_GNUC_CONST; -RpmostreedTransactionMonitor * - rpmostreed_transaction_monitor_new (void); -void rpmostreed_transaction_monitor_add (RpmostreedTransactionMonitor *monitor, - RpmostreedTransaction *transaction); -RpmostreedTransaction * - rpmostreed_transaction_monitor_ref_active_transaction - (RpmostreedTransactionMonitor *monitor); diff --git a/src/daemon/rpmostreed-transaction.c b/src/daemon/rpmostreed-transaction.c index f5803855..fe44edc7 100644 --- a/src/daemon/rpmostreed-transaction.c +++ b/src/daemon/rpmostreed-transaction.c @@ -28,6 +28,7 @@ struct _RpmostreedTransactionPrivate { GDBusMethodInvocation *invocation; + gboolean executed; /* TRUE if the transaction has completed (successfully or not) */ GCancellable *cancellable; /* For the duration of the transaction, we hold a ref to a new @@ -50,7 +51,7 @@ struct _RpmostreedTransactionPrivate { enum { PROP_0, - PROP_ACTIVE, + PROP_EXECUTED, PROP_INVOCATION, PROP_SYSROOT_PATH, PROP_REDIRECT_OUTPUT @@ -98,6 +99,8 @@ transaction_maybe_emit_closed (RpmostreedTransaction *self) return; g_signal_emit (self, signals[CLOSED], 0); + + rpmostreed_sysroot_finish_txn (rpmostreed_sysroot_get (), self); } static void @@ -365,7 +368,8 @@ transaction_execute_done_cb (GObject *source_object, priv->finished_params = g_variant_new ("(bs)", success, error_message); g_variant_ref_sink (priv->finished_params); - g_object_notify (G_OBJECT (self), "active"); + priv->executed = TRUE; + g_object_notify (G_OBJECT (self), "executed"); transaction_maybe_emit_closed (self); } @@ -416,6 +420,9 @@ transaction_get_property (GObject *object, case PROP_REDIRECT_OUTPUT: g_value_set_boolean (value, priv->redirect_output); break; + case PROP_EXECUTED: + g_value_set_boolean (value, priv->executed); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -428,9 +435,6 @@ transaction_dispose (GObject *object) RpmostreedTransaction *self = RPMOSTREED_TRANSACTION (object); RpmostreedTransactionPrivate *priv = rpmostreed_transaction_get_private (self); - if (priv->sysroot != NULL) - ostree_sysroot_unlock (priv->sysroot); - g_hash_table_remove_all (priv->peer_connections); g_clear_object (&priv->invocation); @@ -452,6 +456,9 @@ transaction_finalize (GObject *object) g_debug ("%s (%p): Finalized", G_OBJECT_TYPE_NAME (self), self); + if (priv->sysroot != NULL) + ostree_sysroot_unlock (priv->sysroot); + if (priv->watch_id > 0) g_bus_unwatch_name (priv->watch_id); @@ -490,6 +497,25 @@ transaction_constructed (GObject *object) } } +static gboolean +foreach_close_peer (gpointer key, + gpointer value, + gpointer user_data) +{ + GDBusConnection *conn = key; + g_dbus_connection_close_sync (conn, NULL, NULL); + return TRUE; +} + +void +rpmostreed_transaction_force_close (RpmostreedTransaction *transaction) +{ + RpmostreedTransactionPrivate *priv = rpmostreed_transaction_get_private (transaction); + g_assert (priv->executed); + g_dbus_server_stop (priv->server); + g_hash_table_foreach_remove (priv->peer_connections, foreach_close_peer, NULL); +} + static void on_sysroot_journal_msg (OstreeSysroot *sysroot, const char *msg, @@ -663,11 +689,11 @@ rpmostreed_transaction_class_init (RpmostreedTransactionClass *class) object_class->constructed = transaction_constructed; g_object_class_install_property (object_class, - PROP_ACTIVE, - g_param_spec_boolean ("active", - "Active", - "Whether the transaction is active (unfinished)", - TRUE, + PROP_EXECUTED, + g_param_spec_boolean ("executed", + "Executed", + "Whether the transaction has finished", + FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); @@ -724,6 +750,7 @@ rpmostreed_transaction_dbus_iface_init (RPMOSTreeTransactionIface *iface) static void rpmostreed_transaction_init (RpmostreedTransaction *self) { + g_assert (!rpmostreed_sysroot_has_txn (rpmostreed_sysroot_get ())); self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, RPMOSTREED_TYPE_TRANSACTION, RpmostreedTransactionPrivate); diff --git a/src/daemon/rpmostreed-transaction.h b/src/daemon/rpmostreed-transaction.h index 3ac99dcb..a2675795 100644 --- a/src/daemon/rpmostreed-transaction.h +++ b/src/daemon/rpmostreed-transaction.h @@ -56,3 +56,4 @@ void rpmostreed_transaction_connect_download_progress void rpmostreed_transaction_connect_signature_progress (RpmostreedTransaction *transaction, OstreeRepo *repo); +void rpmostreed_transaction_force_close (RpmostreedTransaction *transaction); diff --git a/src/daemon/rpmostreed-types.h b/src/daemon/rpmostreed-types.h index 714c1aa3..e883d336 100644 --- a/src/daemon/rpmostreed-types.h +++ b/src/daemon/rpmostreed-types.h @@ -39,6 +39,3 @@ typedef struct _RpmostreedOSExperimental RpmostreedOSExperimental; struct _RpmostreedTransaction; typedef struct _RpmostreedTransaction RpmostreedTransaction; - -struct _RpmostreedTransactionMonitor; -typedef struct _RpmostreedTransactionMonitor RpmostreedTransactionMonitor;