[PackageKit/f21] Backport some patches from master to fix some common crashers
Richard Hughes
rhughes at fedoraproject.org
Thu Dec 11 20:15:54 UTC 2014
commit c68a371c17ad292bb27632f61dbb7860bdd97e64
Author: Richard Hughes <richard at hughsie.com>
Date: Thu Dec 11 19:53:54 2014 +0000
Backport some patches from master to fix some common crashers
PackageKit.spec | 9 +-
master.patch | 727 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 735 insertions(+), 1 deletions(-)
---
diff --git a/PackageKit.spec b/PackageKit.spec
index b1a84e9..b40d768 100644
--- a/PackageKit.spec
+++ b/PackageKit.spec
@@ -7,7 +7,7 @@
Summary: Package management service
Name: PackageKit
Version: 1.0.3
-Release: 3%{?dist}
+Release: 4%{?dist}
License: GPLv2+ and LGPLv2+
URL: http://www.freedesktop.org/software/PackageKit/
Source0: http://www.freedesktop.org/software/PackageKit/releases/%{name}-%{version}.tar.xz
@@ -20,6 +20,9 @@ Source1: cached-metadata.tar
# Fedora-specific: set Vendor.conf up for Fedora.
Patch0: PackageKit-0.3.8-Fedora-Vendor.conf.patch
+# already upstream
+Patch1: master.patch
+
Requires: %{name}-glib%{?_isa} = %{version}-%{release}
Requires: shared-mime-info
Requires: comps-extras
@@ -176,6 +179,7 @@ using PackageKit.
%prep
%setup -q
%patch0 -p1 -b .fedora
+%patch1 -p1 -b .master
%build
%configure \
@@ -316,6 +320,9 @@ systemctl disable packagekit-offline-update.service > /dev/null 2>&1 || :
%{_datadir}/gtk-doc/html/PackageKit
%changelog
+* Thu Dec 11 2014 Richard Hughes <rhughes at redhat.com> - 1.0.3-4
+- Backport some patches from master to fix some common crashers.
+
* Mon Nov 17 2014 Kalev Lember <kalevlember at gmail.com> - 1.0.3-3
- Update cached metadata in preparation for F21 release
diff --git a/master.patch b/master.patch
new file mode 100644
index 0000000..ae8eb72
--- /dev/null
+++ b/master.patch
@@ -0,0 +1,727 @@
+commit 0e85001b247c2ed933e5eb028cd167a8e3e40589
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Nov 26 10:58:17 2014 +0000
+
+ command-not-found: Do not attempt to run for anything prefixed with '.'
+
+ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1151185
+
+diff --git a/contrib/command-not-found/pk-command-not-found.c b/contrib/command-not-found/pk-command-not-found.c
+index ef1997e..0843735 100644
+--- a/contrib/command-not-found/pk-command-not-found.c
++++ b/contrib/command-not-found/pk-command-not-found.c
+@@ -778,6 +778,8 @@ main (int argc, char *argv[])
+ len = strlen (argv[1]);
+ if (len < 1)
+ goto out;
++ if (argv[1][0] == '.')
++ goto out;
+
+ /* TRANSLATORS: the prefix of all the output telling the user
+ * why it's not executing. NOTE: this is lowercase to mimic
+commit e2c38732cddd3322470dd7ac008debc9158e98c2
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Dec 3 15:39:25 2014 +0000
+
+ hif: Proxy the allow-cancel state from the state to the job
+
+diff --git a/backends/hif/pk-backend-hif.c b/backends/hif/pk-backend-hif.c
+index 9b7fef1..0aa02df 100644
+--- a/backends/hif/pk-backend-hif.c
++++ b/backends/hif/pk-backend-hif.c
+@@ -353,6 +353,17 @@ pk_backend_speed_changed_cb (HifState *state,
+ }
+
+ /**
++ * pk_backend_state_allow_cancel_changed_cb:
++ **/
++static void
++pk_backend_state_allow_cancel_changed_cb (HifState *state,
++ gboolean allow_cancel,
++ PkBackendJob *job)
++{
++ pk_backend_job_set_allow_cancel (job, allow_cancel);
++}
++
++/**
+ * pk_backend_start_job:
+ */
+ void
+@@ -373,6 +384,9 @@ pk_backend_start_job (PkBackend *backend, PkBackendJob *job)
+ g_signal_connect (job_data->state, "action-changed",
+ G_CALLBACK (pk_backend_state_action_changed_cb),
+ job);
++ g_signal_connect (job_data->state, "allow-cancel-changed",
++ G_CALLBACK (pk_backend_state_allow_cancel_changed_cb),
++ job);
+ g_signal_connect (job_data->state, "notify::speed",
+ G_CALLBACK (pk_backend_speed_changed_cb),
+ job);
+commit b7a1701ac626192fedb376b7b3a7401cf6c59aeb
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Dec 3 17:11:45 2014 +0000
+
+ Save the correct logind cookie when perforing the system-wide inhibit
+
+ It seem we need to use g_dbus_proxy_call_with_unix_fd_list_sync() to actually
+ get the FD number now. This is also the method gnome-session uses.
+
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index e434c88..8dea882 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -37,6 +37,7 @@
+
+ #include <glib/gi18n.h>
+ #include <glib/gstdio.h>
++#include <gio/gunixfdlist.h>
+ #include <packagekit-glib2/pk-offline.h>
+ #include <packagekit-glib2/pk-offline-private.h>
+ #include <packagekit-glib2/pk-version.h>
+@@ -262,9 +263,16 @@ static void
+ pk_engine_inhibit (PkEngine *engine)
+ {
+ #ifdef HAVE_SYSTEMD
++ const gint *fd_list;
++ gint fd_list_len = 0;
+ _cleanup_error_free_ GError *error = NULL;
++ _cleanup_object_unref_ GUnixFDList *out_fd_list = NULL;
+ _cleanup_variant_unref_ GVariant *res = NULL;
+
++ /* already inhibited */
++ if (engine->priv->logind_fd != 0)
++ return;
++
+ /* not yet connected */
+ if (engine->priv->logind_proxy == NULL) {
+ g_warning ("no logind connection to use");
+@@ -272,25 +280,32 @@ pk_engine_inhibit (PkEngine *engine)
+ }
+
+ /* block shutdown and idle */
+- res = g_dbus_proxy_call_sync (engine->priv->logind_proxy,
+- "Inhibit",
+- g_variant_new ("(ssss)",
+- "shutdown:idle",
+- "Package Updater",
+- "Package Update in Progress",
+- "block"),
+- G_DBUS_CALL_FLAGS_NONE,
+- -1,
+- NULL, /* GCancellable */
+- &error);
++ res = g_dbus_proxy_call_with_unix_fd_list_sync (engine->priv->logind_proxy,
++ "Inhibit",
++ g_variant_new ("(ssss)",
++ "shutdown:idle",
++ "Package Updater",
++ "Package Update in Progress",
++ "block"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, /* fd_list */
++ &out_fd_list,
++ NULL, /* GCancellable */
++ &error);
+ if (res == NULL) {
+ g_warning ("Failed to Inhibit using logind: %s", error->message);
+ return;
+ }
+
+ /* keep fd as cookie */
+- g_variant_get (res, "(h)", &engine->priv->logind_fd);
+- g_debug ("got logind cookie %i", engine->priv->logind_fd);
++ fd_list = g_unix_fd_list_peek_fds (out_fd_list, &fd_list_len);
++ if (fd_list_len != 1) {
++ g_warning ("invalid response from logind");
++ return;
++ }
++ engine->priv->logind_fd = fd_list[0];
++ g_debug ("opened logind fd %i", engine->priv->logind_fd);
+ #endif
+ }
+
+@@ -301,10 +316,9 @@ static void
+ pk_engine_uninhibit (PkEngine *engine)
+ {
+ #ifdef HAVE_SYSTEMD
+- if (engine->priv->logind_fd == 0) {
+- g_warning ("no fd to close");
++ if (engine->priv->logind_fd == 0)
+ return;
+- }
++ g_debug ("closed logind fd %i", engine->priv->logind_fd);
+ close (engine->priv->logind_fd);
+ engine->priv->logind_fd = 0;
+ #endif
+commit 8e314593fcf87e276b87bb7f5a9c8710883124a6
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Dec 3 17:15:03 2014 +0000
+
+ trivial: Fix a method name to reflect the new name
+
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index 8dea882..dcb4686 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -162,10 +162,10 @@ pk_engine_reset_timer (PkEngine *engine)
+ }
+
+ /**
+- * pk_engine_transaction_list_changed_cb:
++ * pk_engine_scheduler_changed_cb:
+ **/
+ static void
+-pk_engine_transaction_list_changed_cb (PkScheduler *tlist, PkEngine *engine)
++pk_engine_scheduler_changed_cb (PkScheduler *tlist, PkEngine *engine)
+ {
+ _cleanup_strv_free_ gchar **transaction_list = NULL;
+ gboolean locked;
+@@ -1875,7 +1875,7 @@ pk_engine_new (GKeyFile *conf)
+ pk_scheduler_set_backend (engine->priv->scheduler,
+ engine->priv->backend);
+ g_signal_connect (engine->priv->scheduler, "changed",
+- G_CALLBACK (pk_engine_transaction_list_changed_cb), engine);
++ G_CALLBACK (pk_engine_scheduler_changed_cb), engine);
+ return PK_ENGINE (engine);
+ }
+
+commit 1c019c15929781158cdd6ee67401dd168d34b7d3
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Dec 3 17:20:16 2014 +0000
+
+ Actually inhibit logind when the transaction can't be cancelled
+
+ To do this we have to proxy the allow-cancel state up to the scheduler, and then
+ if any running tasks cannot be cancelled we take the logind inhibit.
+
+ This also means making the initial and final allow-cancel states sane so that
+ the inihibit is registered when required, and also disposed of if not done so
+ manually.
+
+ This commit also unties the confusion between "locked" and "allow-cancel" that
+ existed in multiple places.
+ Backends should use 'allow-cancel' for things actions that cannot be cancelled
+ manually (nor will be the system be allowed to shutdown) and 'locked' for where
+ the package cache is shared and cannot be used by other tools.
+
+diff --git a/src/pk-backend-job.c b/src/pk-backend-job.c
+index af9e9a7..37ee96f 100644
+--- a/src/pk-backend-job.c
++++ b/src/pk-backend-job.c
+@@ -131,6 +131,7 @@ pk_backend_job_reset (PkBackendJob *job)
+ job->priv->finished = FALSE;
+ job->priv->has_sent_package = FALSE;
+ job->priv->set_error = FALSE;
++ job->priv->allow_cancel = TRUE;
+ job->priv->thread = NULL;
+ job->priv->exit = PK_EXIT_ENUM_UNKNOWN;
+ job->priv->role = PK_ROLE_ENUM_UNKNOWN;
+@@ -1711,15 +1712,15 @@ pk_backend_job_set_allow_cancel (PkBackendJob *job, gboolean allow_cancel)
+ }
+
+ /* same as last state? */
+- if (job->priv->allow_cancel == (gboolean) allow_cancel)
++ if (job->priv->allow_cancel == allow_cancel)
+ return;
+
+ /* emit */
++ job->priv->allow_cancel = allow_cancel;
+ pk_backend_job_call_vfunc (job,
+ PK_BACKEND_SIGNAL_ALLOW_CANCEL,
+ GUINT_TO_POINTER (allow_cancel),
+ NULL);
+- job->priv->allow_cancel = allow_cancel;
+ }
+
+ /**
+@@ -1813,8 +1814,8 @@ pk_backend_job_finished (PkBackendJob *job)
+ g_warning ("required status signals for %s!", role_text);
+ }
+
+- /* make any UI insensitive */
+- pk_backend_job_set_allow_cancel (job, FALSE);
++ /* drop any inhibits */
++ pk_backend_job_set_allow_cancel (job, TRUE);
+
+ /* mark as finished for the UI that might only be watching status */
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_FINISHED);
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index dcb4686..92b020f 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -161,22 +161,39 @@ pk_engine_reset_timer (PkEngine *engine)
+ g_timer_reset (engine->priv->timer);
+ }
+
++static void pk_engine_inhibit (PkEngine *engine);
++static void pk_engine_uninhibit (PkEngine *engine);
++
++/**
++ * pk_engine_set_inhibited:
++ **/
++static void
++pk_engine_set_inhibited (PkEngine *engine, gboolean inhibited)
++{
++ g_return_if_fail (PK_IS_ENGINE (engine));
++
++ /* inhibit shutdown and suspend */
++ if (inhibited)
++ pk_engine_inhibit (engine);
++ else
++ pk_engine_uninhibit (engine);
++}
++
+ /**
+ * pk_engine_scheduler_changed_cb:
+ **/
+ static void
+-pk_engine_scheduler_changed_cb (PkScheduler *tlist, PkEngine *engine)
++pk_engine_scheduler_changed_cb (PkScheduler *scheduler, PkEngine *engine)
+ {
+ _cleanup_strv_free_ gchar **transaction_list = NULL;
+- gboolean locked;
+
+ g_return_if_fail (PK_IS_ENGINE (engine));
+
+ /* automatically locked if the transaction cannot be cancelled */
+- locked = pk_scheduler_get_locked (tlist);
+- pk_engine_set_locked (engine, locked);
++ pk_engine_set_locked (engine, pk_scheduler_get_locked (scheduler));
++ pk_engine_set_inhibited (engine, pk_scheduler_get_inhibited (scheduler));
+
+- transaction_list = pk_scheduler_get_array (engine->priv->scheduler);
++ transaction_list = pk_scheduler_get_array (scheduler);
+ g_dbus_connection_emit_signal (engine->priv->connection,
+ NULL,
+ PK_DBUS_PATH,
+@@ -337,12 +354,6 @@ pk_engine_set_locked (PkEngine *engine, gboolean is_locked)
+ return;
+ engine->priv->locked = is_locked;
+
+- /* inhibit shutdown and suspend */
+- if (is_locked)
+- pk_engine_inhibit (engine);
+- else
+- pk_engine_uninhibit (engine);
+-
+ /* emit */
+ pk_engine_emit_property_changed (engine,
+ "Locked",
+diff --git a/src/pk-scheduler.c b/src/pk-scheduler.c
+index c9415ef..fa81a97 100644
+--- a/src/pk-scheduler.c
++++ b/src/pk-scheduler.c
+@@ -105,6 +105,7 @@ typedef struct {
+ guint commit_id;
+ gulong finished_id;
+ gulong state_changed_id;
++ gulong allow_cancel_changed_id;
+ guint uid;
+ guint tries;
+ } PkSchedulerItem;
+@@ -202,6 +203,8 @@ pk_scheduler_item_free (PkSchedulerItem *item)
+ g_signal_handler_disconnect (item->transaction, item->finished_id);
+ if (item->state_changed_id != 0)
+ g_signal_handler_disconnect (item->transaction, item->state_changed_id);
++ if (item->allow_cancel_changed_id != 0)
++ g_signal_handler_disconnect (item->transaction, item->allow_cancel_changed_id);
+ g_object_unref (item->transaction);
+ if (item->commit_id != 0)
+ g_source_remove (item->commit_id);
+@@ -514,6 +517,18 @@ pk_scheduler_commit (PkScheduler *scheduler, const gchar *tid)
+ }
+
+ /**
++ * pk_scheduler_transaction_allow_cancel_changed_cb:
++ **/
++static void
++pk_scheduler_transaction_allow_cancel_changed_cb (PkTransaction *transaction,
++ gboolean allow_cancel,
++ PkScheduler *scheduler)
++{
++ /* just proxy this back up */
++ g_signal_emit (scheduler, signals [PK_SCHEDULER_CHANGED], 0);
++}
++
++/**
+ * pk_scheduler_transaction_state_changed_cb:
+ **/
+ static void
+@@ -678,6 +693,10 @@ pk_scheduler_create (PkScheduler *scheduler,
+ g_signal_connect_after (item->transaction, "state-changed",
+ G_CALLBACK (pk_scheduler_transaction_state_changed_cb),
+ scheduler);
++ item->allow_cancel_changed_id =
++ g_signal_connect_after (item->transaction, "allow-cancel-changed",
++ G_CALLBACK (pk_scheduler_transaction_allow_cancel_changed_cb),
++ scheduler);
+
+ /* set transaction state */
+ pk_transaction_set_state (item->transaction, PK_TRANSACTION_STATE_NEW);
+@@ -736,7 +755,7 @@ pk_scheduler_create (PkScheduler *scheduler,
+ * pk_scheduler_get_locked:
+ *
+ * Return value: %TRUE if any of the transactions in progress are
+- * locking a database or resource and cannot be cancelled.
++ * locking the packaging system.
+ **/
+ gboolean
+ pk_scheduler_get_locked (PkScheduler *scheduler)
+@@ -748,19 +767,43 @@ pk_scheduler_get_locked (PkScheduler *scheduler)
+
+ g_return_val_if_fail (PK_IS_SCHEDULER (scheduler), FALSE);
+
+- /* anything running? */
++ /* check if any backend in running transaction is locked at time */
+ array = pk_scheduler_get_active_transactions (scheduler);
+- if (array->len == 0)
+- return FALSE;
++ for (i = 0; i < array->len; i++) {
++ item = g_ptr_array_index (array, i);
++ job = pk_transaction_get_backend_job (item->transaction);
++ if (job == NULL)
++ continue;
++ if (pk_backend_job_get_locked (job))
++ return TRUE;
++ }
++ return FALSE;
++}
++
++/**
++ * pk_scheduler_get_inhibited:
++ *
++ * Return value: %TRUE if any of the transactions in progress cannot be
++ * cancelled.
++ **/
++gboolean
++pk_scheduler_get_inhibited (PkScheduler *scheduler)
++{
++ PkBackendJob *job;
++ PkSchedulerItem *item;
++ guint i;
++ _cleanup_ptrarray_unref_ GPtrArray *array = NULL;
++
++ g_return_val_if_fail (PK_IS_SCHEDULER (scheduler), FALSE);
+
+ /* check if any backend in running transaction is locked at time */
++ array = pk_scheduler_get_active_transactions (scheduler);
+ for (i = 0; i < array->len; i++) {
+- item = (PkSchedulerItem *) g_ptr_array_index (array, i);
+-
++ item = g_ptr_array_index (array, i);
+ job = pk_transaction_get_backend_job (item->transaction);
+ if (job == NULL)
+ continue;
+- if (pk_backend_job_get_locked (job))
++ if (!pk_backend_job_get_allow_cancel (job))
+ return TRUE;
+ }
+ return FALSE;
+diff --git a/src/pk-scheduler.h b/src/pk-scheduler.h
+index 398e4ff..d394dc8 100644
+--- a/src/pk-scheduler.h
++++ b/src/pk-scheduler.h
+@@ -68,6 +68,7 @@ gchar *pk_scheduler_get_state (PkScheduler *scheduler)
+ G_GNUC_WARN_UNUSED_RESULT;
+ guint pk_scheduler_get_size (PkScheduler *scheduler);
+ gboolean pk_scheduler_get_locked (PkScheduler *scheduler);
++gboolean pk_scheduler_get_inhibited (PkScheduler *scheduler);
+ PkTransaction *pk_scheduler_get_transaction (PkScheduler *scheduler,
+ const gchar *tid);
+ void pk_scheduler_cancel_background (PkScheduler *scheduler);
+diff --git a/src/pk-transaction.c b/src/pk-transaction.c
+index 6485bb5..33245d8 100644
+--- a/src/pk-transaction.c
++++ b/src/pk-transaction.c
+@@ -170,6 +170,7 @@ typedef enum {
+ enum {
+ SIGNAL_FINISHED,
+ SIGNAL_STATE_CHANGED,
++ SIGNAL_ALLOW_CANCEL_CHANGED,
+ SIGNAL_LAST
+ };
+
+@@ -384,7 +385,8 @@ pk_transaction_allow_cancel_emit (PkTransaction *transaction, gboolean allow_can
+
+ transaction->priv->allow_cancel = allow_cancel;
+
+- /* TODO: have master property on main interface */
++ /* proxy this up so we can change the system inhibit */
++ g_signal_emit (transaction, signals[SIGNAL_ALLOW_CANCEL_CHANGED], 0, allow_cancel);
+
+ /* emit */
+ pk_transaction_emit_property_changed (transaction,
+@@ -1101,10 +1103,6 @@ pk_transaction_finished_cb (PkBackendJob *job, PkExitEnum exit_enum, PkTransacti
+ pk_transaction_offline_finished (transaction);
+ }
+
+- /* if we did not send this, ensure the GUI has the right state */
+- if (transaction->priv->allow_cancel)
+- pk_transaction_allow_cancel_emit (transaction, FALSE);
+-
+ /* we should get no more from the backend with this tid */
+ transaction->priv->finished = TRUE;
+
+@@ -1796,9 +1794,6 @@ pk_transaction_run (PkTransaction *transaction)
+ priv->tid,
+ pk_role_enum_to_string (priv->role));
+
+- /* mark running */
+- priv->allow_cancel = FALSE;
+-
+ /* reset after the pre-transaction checks */
+ pk_backend_job_set_percentage (priv->job, PK_BACKEND_PERCENTAGE_INVALID);
+
+@@ -5408,6 +5403,11 @@ pk_transaction_class_init (PkTransactionClass *klass)
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
++ signals[SIGNAL_ALLOW_CANCEL_CHANGED] =
++ g_signal_new ("allow-cancel-changed",
++ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
++ 0, NULL, NULL, g_cclosure_marshal_VOID__UINT,
++ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+ g_type_class_add_private (klass, sizeof (PkTransactionPrivate));
+ }
+commit 85a02c15fb1bf05e109d53ecd02b38baf410408a
+Author: Richard Hughes <richard at hughsie.com>
+Date: Wed Dec 10 18:12:27 2014 +0000
+
+ Make pk_backend_repo_list_changed() threadsafe
+
+diff --git a/src/pk-backend.c b/src/pk-backend.c
+index 78191c1..4c45f0f 100644
+--- a/src/pk-backend.c
++++ b/src/pk-backend.c
+@@ -210,6 +210,8 @@ struct PkBackendPrivate
+ GMutex thread_hash_mutex;
+ gboolean transaction_in_progress;
+ guint transaction_inhibit_end_idle_id;
++ guint repo_list_changed_id;
++ guint installed_db_changed_id;
+ };
+
+ G_DEFINE_TYPE (PkBackend, pk_backend, G_TYPE_OBJECT)
+@@ -633,20 +635,58 @@ pk_backend_unload (PkBackend *backend)
+ }
+
+ /**
+- * pk_backend_repo_list_changed:
++ * pk_backend_repo_list_changed_cb:
+ **/
+-void
+-pk_backend_repo_list_changed (PkBackend *backend)
++static gboolean
++pk_backend_repo_list_changed_cb (gpointer user_data)
+ {
++ PkBackend *backend = PK_BACKEND (user_data);
+ #ifdef PK_BUILD_DAEMON
+ _cleanup_object_unref_ PkNotify *notify = NULL;
++ notify = pk_notify_new ();
++ pk_notify_repo_list_changed (notify);
++#endif
++ backend->priv->repo_list_changed_id = 0;
++ return FALSE;
++}
+
++/**
++ * pk_backend_repo_list_changed:
++ *
++ * This function can be called on any thread.
++ **/
++void
++pk_backend_repo_list_changed (PkBackend *backend)
++{
+ g_return_if_fail (PK_IS_BACKEND (backend));
+ g_return_if_fail (backend->priv->loaded);
+
+- notify = pk_notify_new ();
+- pk_notify_repo_list_changed (notify);
+-#endif
++ /* already scheduled */
++ if (backend->priv->repo_list_changed_id != 0)
++ return;
++
++ /* idle add */
++ backend->priv->repo_list_changed_id =
++ g_idle_add (pk_backend_repo_list_changed_cb, backend);
++
++}
++
++/**
++ * pk_backend_installed_db_changed_cb:
++ **/
++static gboolean
++pk_backend_installed_db_changed_cb (gpointer user_data)
++{
++ PkBackend *backend = PK_BACKEND (user_data);
++ _cleanup_error_free_ GError *error = NULL;
++
++ if (!backend->priv->transaction_in_progress) {
++ g_debug ("invalidating offline updates");
++ if (!pk_offline_auth_invalidate (&error))
++ g_warning ("failed to invalidate: %s", error->message);
++ }
++ backend->priv->installed_db_changed_id = 0;
++ return FALSE;
+ }
+
+ /**
+@@ -661,20 +701,22 @@ pk_backend_repo_list_changed (PkBackend *backend)
+ * transactions done by PackageKit itself, a backend would call
+ * pk_backend_transaction_inhibit_start() before each transaction and
+ * pk_backend_transaction_inhibit_end() after the transaction has finished.
++ *
++ * This function can be called on any thread.
+ **/
+ void
+ pk_backend_installed_db_changed (PkBackend *backend)
+ {
+- _cleanup_error_free_ GError *error = NULL;
+-
+ g_return_if_fail (PK_IS_BACKEND (backend));
+ g_return_if_fail (backend->priv->loaded);
+
+- if (!backend->priv->transaction_in_progress) {
+- g_debug ("invalidating offline updates");
+- if (!pk_offline_auth_invalidate (&error))
+- g_warning ("failed to invalidate: %s", error->message);
+- }
++ /* already scheduled */
++ if (backend->priv->installed_db_changed_id != 0)
++ return;
++
++ /* idle add */
++ backend->priv->installed_db_changed_id =
++ g_idle_add (pk_backend_installed_db_changed_cb, backend);
+ }
+
+ /**
+commit 52dbba80288f292909b6af0f20a78ada498ca213
+Author: Richard Hughes <richard at hughsie.com>
+Date: Thu Dec 11 10:11:33 2014 +0000
+
+ Fix a hard-to-debug crash when cancelling a task that has never been run
+
+ Calling g_dbus_method_invocation_return_value() twice for the same
+ GDBusMethodInvocation is a bad idea that manifests in a backtrace like:
+
+ > g_source_callback_unref (cb_data) at gmain.c:1532
+ > g_source_destroy_internal (source, context, have_lock=1) at gmain.c:1178
+ > g_main_context_dispatch (context) at gmain.c:3134
+
+ > (gdb) p g_source_get_name(source)
+ > $1 = '[gio] call_in_idle_cb'
+
+diff --git a/src/pk-transaction.c b/src/pk-transaction.c
+index 0f3dd8d..93295de 100644
+--- a/src/pk-transaction.c
++++ b/src/pk-transaction.c
+@@ -2911,7 +2911,6 @@ skip_uid:
+ PK_ERROR_ENUM_TRANSACTION_CANCELLED,
+ msg);
+ pk_transaction_finished_emit (transaction, PK_EXIT_ENUM_CANCELLED, 0);
+- pk_transaction_dbus_return (context, NULL);
+ goto out;
+ }
+
+commit 71a8f25ce05ee4d9177db288317e86512b989232
+Author: Richard Hughes <richard at hughsie.com>
+Date: Thu Dec 11 10:31:57 2014 +0000
+
+ Make pk_backend_job_call_vfunc() threadsafe
+
+ We have to keep a ref to PkBackendJob until the lifecycle is properly fixed.
+
+diff --git a/src/pk-backend-job.c b/src/pk-backend-job.c
+index 73162e4..c1c5ca6 100644
+--- a/src/pk-backend-job.c
++++ b/src/pk-backend-job.c
+@@ -657,6 +657,18 @@ pk_backend_job_signal_to_string (PkBackendJobSignal id)
+ }
+
+ /**
++ * pk_backend_job_vfunc_event_free:
++ **/
++static void
++pk_backend_job_vfunc_event_free (PkBackendJobVFuncHelper *helper)
++{
++ if (helper->destroy_func != NULL)
++ helper->destroy_func (helper->object);
++ g_object_unref (helper->job);
++ g_free (helper);
++}
++
++/**
+ * pk_backend_job_call_vfunc_idle_cb:
+ **/
+ static gboolean
+@@ -673,8 +685,6 @@ pk_backend_job_call_vfunc_idle_cb (gpointer user_data)
+ g_warning ("tried to do signal %s when no longer connected",
+ pk_backend_job_signal_to_string (helper->signal_kind));
+ }
+- if (helper->destroy_func != NULL)
+- helper->destroy_func (helper->object);
+ return FALSE;
+ }
+
+@@ -693,25 +703,31 @@ pk_backend_job_call_vfunc (PkBackendJob *job,
+ PkBackendJobVFuncHelper *helper;
+ PkBackendJobVFuncItem *item;
+ guint priority = G_PRIORITY_DEFAULT_IDLE;
++ _cleanup_source_unref_ GSource *source = NULL;
+
+ /* call transaction vfunc if not disabled and set */
+ item = &job->priv->vfunc_items[signal_kind];
+ if (!item->enabled || item->vfunc == NULL)
+ return;
+
++ /* order this last if others are still pending */
+ if (signal_kind == PK_BACKEND_SIGNAL_FINISHED)
+ priority = G_PRIORITY_LOW;
+
+- /* emit idle, TODO: do we ever need to cancel this? */
++ /* emit idle */
+ helper = g_new0 (PkBackendJobVFuncHelper, 1);
+- helper->job = job;
++ helper->job = g_object_ref (job);
+ helper->signal_kind = signal_kind;
+ helper->object = object;
+ helper->destroy_func = destroy_func;
+- g_idle_add_full (priority,
+- pk_backend_job_call_vfunc_idle_cb,
+- helper,
+- g_free);
++ source = g_idle_source_new ();
++ g_source_set_priority (source, priority);
++ g_source_set_callback (source,
++ pk_backend_job_call_vfunc_idle_cb,
++ helper,
++ (GDestroyNotify) pk_backend_job_vfunc_event_free);
++ g_source_set_name (source, "[PkBackendJob] idle_event_cb");
++ g_source_attach (source, NULL);
+ }
+
+ /**
+diff --git a/src/pk-cleanup.h b/src/pk-cleanup.h
+index 7a04561..ee511dc 100644
+--- a/src/pk-cleanup.h
++++ b/src/pk-cleanup.h
+@@ -57,6 +57,7 @@ GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_
+ GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_keyfile_unref, g_key_file_unref)
+ GS_DEFINE_CLEANUP_FUNCTION0(GMarkupParseContext*, gs_local_markup_parse_context_unref, g_markup_parse_context_unref)
+ GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref)
++GS_DEFINE_CLEANUP_FUNCTION0(GSource*, gs_local_source_unref, g_source_unref)
+ GS_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, gs_local_ptrarray_unref, g_ptr_array_unref)
+ GS_DEFINE_CLEANUP_FUNCTION0(GTimer*, gs_local_destroy_timer, g_timer_destroy)
+ GS_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, gs_local_variant_builder_unref, g_variant_builder_unref)
+@@ -86,6 +87,7 @@ GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
+ #define _cleanup_keyfile_unref_ __attribute__ ((cleanup(gs_local_keyfile_unref)))
+ #define _cleanup_markup_parse_context_unref_ __attribute__ ((cleanup(gs_local_markup_parse_context_unref)))
+ #define _cleanup_object_unref_ __attribute__ ((cleanup(gs_local_obj_unref)))
++#define _cleanup_source_unref_ __attribute__ ((cleanup(gs_local_source_unref)))
+ #define _cleanup_ptrarray_unref_ __attribute__ ((cleanup(gs_local_ptrarray_unref)))
+ #define _cleanup_variant_unref_ __attribute__ ((cleanup(gs_local_variant_unref)))
+ #define _cleanup_main_loop_unref_ __attribute__ ((cleanup(gs_local_main_loop_unref)))
More information about the scm-commits
mailing list