[packagekit] packagekit: Branch 'master' - 6 commits

Richard Hughes hughsient at kemper.freedesktop.org
Thu Oct 18 23:21:06 PDT 2007


 TODO                               |   12 +-
 backends/box/pk-backend-box.c      |   16 ---
 backends/yum/helpers/yumBackend.py |   26 ++---
 src/pk-backend.c                   |    2 
 src/pk-spawn.c                     |  169 ++++++++++++++++++++++++++++++++++---
 5 files changed, 178 insertions(+), 47 deletions(-)

New commits:
commit fec2d1528bd36434124dcec95bcfd46b7ff61d54
Author: Tim Lauridsen <timlau at fedoraproject.org>
Date:   Fri Oct 19 07:40:08 2007 +0200

    yum: added retry on yum lock every 2 sek and submitting wait status to frontend

diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
index b6be476..15f5a1a 100644
--- a/backends/yum/helpers/yumBackend.py
+++ b/backends/yum/helpers/yumBackend.py
@@ -37,6 +37,7 @@ import rpmUtils
 import exceptions
 import types
 import signal
+import time
 
 yumbase = None
 
@@ -68,15 +69,20 @@ class PackageKitYumBackend(PackageKitBaseBackend):
         if lock:
             self.doLock()
         
+ 
     def doLock(self):
         ''' Lock Yum'''
-        if not self.isLocked():        
+        retries = 0
+        while not self.isLocked():
             try: # Try to lock yum
                 self.yumbase.doLock( YUM_PID_FILE )
                 PackageKitBaseBackend.doLock(self)
             except:
-                self.error(ERROR_INTERNAL_ERROR,'Yum is locked by another application')
-                       
+                self.status(STATE_WAIT)
+                time.sleep(2)
+                retries += 1
+                if retries > 100:
+                    self.error(ERROR_INTERNAL_ERROR,'Yum is locked by another application')
 
         
     def unLock(self):        
commit 7ca0e0bec90c658711645d8cba45b3c4f13b4a69
Merge: ab9037c... 108a433...
Author: Grzegorz Dabrowski <gdx at o2.pl>
Date:   Fri Oct 19 07:40:08 2007 +0000

    Merge branch 'master' of git+ssh://kaliber@git.packagekit.org/srv/git/PackageKit

commit ab9037cc2a37744518070291933aa960dcf4c972
Author: Grzegorz Dabrowski <gdx at o2.pl>
Date:   Fri Oct 19 07:39:45 2007 +0000

    [box] backend_get_groups is not supported

diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c
index 9fbe433..a253981 100644
--- a/backends/box/pk-backend-box.c
+++ b/backends/box/pk-backend-box.c
@@ -315,20 +315,6 @@ backend_destroy (PkBackend *backend)
 }
 
 /**
- * backend_get_groups:
- */
-static void
-backend_get_groups (PkBackend *backend, PkEnumList *elist)
-{
-	g_return_if_fail (backend != NULL);
-	pk_enum_list_append_multiple (elist,
-				      PK_GROUP_ENUM_ACCESSIBILITY,
-				      PK_GROUP_ENUM_GAMES,
-				      PK_GROUP_ENUM_SYSTEM,
-				      -1);
-}
-
-/**
  * backend_get_filters:
  */
 static void
@@ -494,7 +480,7 @@ PK_BACKEND_OPTIONS (
 	"Grzegorz DÄ…browski <gdx at o2.pl>",	/* author */
 	backend_initalize,			/* initalize */
 	backend_destroy,			/* destroy */
-	backend_get_groups,			/* get_groups */
+	NULL,					/* get_groups */
 	backend_get_filters,			/* get_filters */
 	NULL,					/* cancel */
 	NULL,					/* get_depends */
commit 108a4337d67dddc9acb218c0fe3ea960492b9db4
Author: Tim Lauridsen <timlau at fedoraproject.org>
Date:   Fri Oct 19 07:26:09 2007 +0200

    yum: clean up unused code

diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
index eef882e..b6be476 100644
--- a/backends/yum/helpers/yumBackend.py
+++ b/backends/yum/helpers/yumBackend.py
@@ -366,7 +366,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
                 else:
                     if self._installable(pkg):
                         self.package(id, INFO_AVAILABLE, pkg.summary)
-        self._unlock_yum()
 
 
     def update_system(self):
@@ -381,7 +380,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
             self._runYumTransaction()
         else:
             self.error(ERROR_INTERNAL_ERROR,"Nothing to do")
-        self._unlock_yum()
 
     def refresh_cache(self):
         '''
@@ -457,7 +455,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
                 self.error(ERROR_PACKAGE_ALREADY_INSTALLED,msgs)
         else:
             self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"Package was not found")
-        self._lock_yum()
 
     def _localInstall(self, inst_file):
         """handles installs/updates of rpms provided on the filesystem in a 
@@ -542,7 +539,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
         '''
         self.allow_interrupt(False);
         self.percentage(0)
-        self._lock_yum()
 
         pkgs_to_inst = []
         self.yumbase.conf.gpgcheck=0
@@ -661,7 +657,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
         '''
         self.allow_interrupt(True)
         self.percentage(None)
-        self._lock_yum()
+
         pkg,inst = self._findPackage(package)
         if pkg:
             pkgver = self._get_package_ver(pkg)
@@ -701,7 +697,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
         '''
         self.allow_interrupt(True)
         self.percentage(None)
-        self._lock_yum()
         md = UpdateMetadata()
         # Added extra Update Metadata
         for repo in self.yumbase.repos.listEnabled():
@@ -741,13 +736,6 @@ class PackageKitYumBackend(PackageKitBaseBackend):
         self.dnlCallback = DownloadCallback(self,showNames=True)  # Download callback
         self.yumbase.repos.setProgressBar( self.dnlCallback )     # Setup the download callback class
 
-    def _lock_yum(self):
-        self.yumbase.doLock( YUM_PID_FILE )       
-
-        
-    def _unlock_yum(self):
-        self.yumbase.doUnlock(YUM_PID_FILE)
-
 class DownloadCallback( BaseMeter ):
     """ Customized version of urlgrabber.progress.BaseMeter class """
     def __init__(self,base,showNames = False):
commit 202875721ad91f075fcd9b7f2428f1e126a3ece1
Author: James Bowes <jbowes at dangerouslyinc.com>
Date:   Thu Oct 18 21:05:13 2007 -0400

    backend: Allow no-percentage-updates to work.
    
    no-percentage-updates has no parameters passed along from the
    backends, so strstr looking for tabs will always fail. Get rid of the
    strstr check.

diff --git a/src/pk-backend.c b/src/pk-backend.c
index d7eecc0..16eeef9 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -330,7 +330,7 @@ pk_backend_parse_common_error (PkBackend *backend, const gchar *line)
 	gboolean ret = TRUE;
 
 	/* check if output line */
-	if (line == NULL || strstr (line, "\t") == NULL)
+	if (line == NULL)
 		return FALSE;
 
 	/* split by tab */
commit 8c311c01e337ed21a8ec548cfaa00303079ae0c3
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Oct 19 00:17:23 2007 +0100

    do SIGQUIT and then SIGKILL after a little delay, so we can unlock the yum backend nicely when we cancel

diff --git a/TODO b/TODO
index 9b4ca02..474a139 100644
--- a/TODO
+++ b/TODO
@@ -44,7 +44,13 @@ if not a valid package_id then
 *** Unit tests ***
 PkSpawn is a complex and untested bit of code.
 
-*** Send SIGQUIT ***
-Do SIGKILL only if SIGQUIT didn't work...
-
+*** PkSpawn enum return value ***
+pk_test_finished_cb (PkSpawn *spawn, gint exitcode, gpointer data)
+- exitcode is undefined - make an enum
+	PK_SPAWN_EXIT_SUCCESS
+	PK_SPAWN_EXIT_FAILED
+	PK_SPAWN_EXIT_KILLED
+
+*** backend docbook ***
+Explain SIGQUIT and SIGKILL in the docs
 
diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index dcb0fcb..ba96c85 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -51,6 +51,7 @@ static void     pk_spawn_finalize	(GObject       *object);
 
 #define PK_SPAWN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_SPAWN, PkSpawnPrivate))
 #define PK_SPAWN_POLL_DELAY	100 /* ms */
+#define PK_SPAWN_SIGKILL_DELAY	500 /* ms */
 
 struct PkSpawnPrivate
 {
@@ -58,6 +59,8 @@ struct PkSpawnPrivate
 	gint			 stderr_fd;
 	gint			 stdout_fd;
 	guint			 poll_id;
+	guint			 kill_id;
+	gboolean		 finished;
 	GString			*stderr_buf;
 	GString			*stdout_buf;
 };
@@ -148,6 +151,11 @@ pk_spawn_check_child (PkSpawn *spawn)
 {
 	int status;
 
+	/* this shouldn't happen */
+	if (spawn->priv->finished == TRUE) {
+		pk_error ("finished twice!");
+	}
+
 	pk_spawn_read_fd_into_buffer (spawn->priv->stdout_fd, spawn->priv->stdout_buf);
 	pk_spawn_read_fd_into_buffer (spawn->priv->stderr_fd, spawn->priv->stderr_buf);
 	pk_spawn_emit_whole_lines (spawn, spawn->priv->stdout_buf, TRUE);
@@ -157,6 +165,9 @@ pk_spawn_check_child (PkSpawn *spawn)
 	if (waitpid (spawn->priv->child_pid, &status, WNOHANG) != spawn->priv->child_pid)
 		return TRUE;
 
+	/* disconnect the poll as there will be no more updates */
+	g_source_remove (spawn->priv->poll_id);
+
 	/* child exited, display some information... */
 	close (spawn->priv->stderr_fd);
 	close (spawn->priv->stdout_fd);
@@ -167,6 +178,15 @@ pk_spawn_check_child (PkSpawn *spawn)
 		pk_debug ("Running fork successful");
 	}
 
+	/* officially done, although no signal yet */
+	spawn->priv->finished = TRUE;
+
+	/* if we are trying to kill this process, cancel the SIGKILL */
+	if (spawn->priv->kill_id != 0) {
+		g_source_remove (spawn->priv->kill_id);
+		spawn->priv->kill_id = 0;
+	}
+
 	pk_debug ("emitting finished %i", WEXITSTATUS (status));
 	g_signal_emit (spawn, signals [PK_SPAWN_FINISHED], 0, WEXITSTATUS (status));
 
@@ -174,28 +194,65 @@ pk_spawn_check_child (PkSpawn *spawn)
 }
 
 /**
+ * pk_spawn_check_child:
+ **/
+static gboolean
+pk_spawn_sigkill_cb (PkSpawn *spawn)
+{
+	gint retval;
+
+	/* check if process has already gone */
+	if (spawn->priv->finished == TRUE) {
+		pk_warning ("already finished, ignoring");
+		return FALSE;
+	}
+
+	pk_warning ("sending SIGKILL %i", spawn->priv->child_pid);
+	retval = kill (spawn->priv->child_pid, SIGKILL);
+	if (retval == EINVAL) {
+		pk_warning ("The signum argument is an invalid or unsupported number");
+		return FALSE;
+	} else if (retval == EPERM) {
+		pk_warning ("You do not have the privilege to send a signal to the process");
+		return FALSE;
+	}
+
+	return FALSE;
+}
+
+/**
  * pk_spawn_kill:
  *
  * THIS IS A VERY DANGEROUS THING TO DO!
  *
+ * We send SIGQUIT and after a few ms SIGKILL
+ *
  **/
 gboolean
 pk_spawn_kill (PkSpawn *spawn)
 {
 	gint retval;
-	guint ret;
-	pk_warning ("killing %i", spawn->priv->child_pid);
-	retval = kill (spawn->priv->child_pid, SIGKILL);
 
-	ret = TRUE;
+	/* check if process has already gone */
+	if (spawn->priv->finished == TRUE) {
+		pk_warning ("already finished, ignoring");
+		return FALSE;
+	}
+
+	pk_warning ("sending SIGQUIT %i", spawn->priv->child_pid);
+	retval = kill (spawn->priv->child_pid, SIGQUIT);
 	if (retval == EINVAL) {
 		pk_warning ("The signum argument is an invalid or unsupported number");
-		ret = FALSE;
+		return FALSE;
 	} else if (retval == EPERM) {
 		pk_warning ("You do not have the privilege to send a signal to the process");
-		ret = FALSE;
+		return FALSE;
 	}
-	return ret;
+
+	/* the program might not be able to handle SIGQUIT, give it a few seconds and then SIGKILL it */
+	spawn->priv->kill_id = g_timeout_add (PK_SPAWN_SIGKILL_DELAY, (GSourceFunc) pk_spawn_sigkill_cb, spawn);
+
+	return TRUE;
 }
 
 /**
@@ -216,6 +273,7 @@ pk_spawn_command (PkSpawn *spawn, const gchar *command)
 	}
 
 	pk_debug ("command '%s'", command);
+	spawn->priv->finished = FALSE;
 
 	/* split command line */
 	argv = g_strsplit (command, " ", 0);
@@ -289,6 +347,8 @@ pk_spawn_init (PkSpawn *spawn)
 	spawn->priv->stderr_fd = -1;
 	spawn->priv->stdout_fd = -1;
 	spawn->priv->poll_id = 0;
+	spawn->priv->kill_id = 0;
+	spawn->priv->finished = FALSE;
 
 	spawn->priv->stderr_buf = g_string_new ("");
 	spawn->priv->stdout_buf = g_string_new ("");
@@ -311,7 +371,14 @@ pk_spawn_finalize (GObject *object)
 	g_return_if_fail (spawn->priv != NULL);
 
 	/* disconnect the poll in case we were cancelled before completion */
-	g_source_remove (spawn->priv->poll_id);
+	if (spawn->priv->poll_id != 0) {
+		g_source_remove (spawn->priv->poll_id);
+	}
+
+	/* disconnect the SIGKILL check */
+	if (spawn->priv->kill_id != 0) {
+		g_source_remove (spawn->priv->kill_id);
+	}
 
 	/* free the buffers */
 	g_string_free (spawn->priv->stderr_buf, TRUE);
@@ -340,6 +407,10 @@ pk_spawn_new (void)
 #include <libselftest.h>
 
 static GMainLoop *loop;
+gint mexitcode = -1;
+guint stdout_count = 0;
+guint stderr_count = 0;
+guint finished_count = 0;
 
 /**
  * pk_test_finished_cb:
@@ -348,6 +419,8 @@ static void
 pk_test_finished_cb (PkSpawn *spawn, gint exitcode, LibSelfTest *test)
 {
 	pk_debug ("spawn exitcode=%i", exitcode);
+	mexitcode = exitcode;
+	finished_count++;
 	g_main_loop_quit (loop);
 }
 
@@ -358,6 +431,7 @@ static void
 pk_test_stdout_cb (PkSpawn *spawn, const gchar *line, LibSelfTest *test)
 {
 	pk_debug ("stdout '%s'", line);
+	stdout_count++;
 }
 
 /**
@@ -367,6 +441,15 @@ static void
 pk_test_stderr_cb (PkSpawn *spawn, const gchar *line, LibSelfTest *test)
 {
 	pk_debug ("stderr '%s'", line);
+	stderr_count++;
+}
+
+static gboolean
+cancel_cb (gpointer data)
+{
+	PkSpawn *spawn = PK_SPAWN(data);
+	pk_spawn_kill (spawn);
+	return FALSE;
 }
 
 void
@@ -389,28 +472,90 @@ libst_spawn (LibSelfTest *test)
 
 	/************************************************************/
 	libst_title (test, "make sure return error for missing file");
+	mexitcode = -1;
 	ret = pk_spawn_command (spawn, "./pk-spawn-test-xxx.sh");
 	if (ret == FALSE) {
 		libst_success (test, "failed to run invalid file");
 	} else {
 		libst_failed (test, "ran incorrect file");
 	}
-
 #if 0
 	/************************************************************/
+	libst_title (test, "make sure finished wasn't called");
+	if (mexitcode == -1) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "Called finish for bad file!");
+	}
+
+	/************************************************************/
 	libst_title (test, "make sure run correct helper");
+	mexitcode = -1;
 	ret = pk_spawn_command (spawn, "./pk-spawn-test.sh");
 	if (ret == TRUE) {
 		libst_success (test, "ran correct file");
 	} else {
 		libst_failed (test, "did not run helper");
 	}
-#endif
 
-#if 0
-	/* spin for a bit */
+	/* spin for a bit, todo add timer to break out if we fail */
+	loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (loop);
+
+	/************************************************************/
+	libst_title (test, "make sure finished okay");
+	if (mexitcode == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "finish was okay!");
+	}
+
+	/************************************************************/
+	libst_title (test, "make sure finished was called only once");
+	if (finished_count == 1) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "finish was called %i times!", finished_count);
+	}
+
+	/************************************************************/
+	libst_title (test, "make sure we got the right stdout data");
+	if (stdout_count == 4) {
+		libst_success (test, "correct stdout count");
+	} else {
+		libst_failed (test, "wrong stdout count %i", stdout_count);
+	}
+
+	/************************************************************/
+	libst_title (test, "make sure we got the right stderr data");
+	if (stderr_count == 11) {
+		libst_success (test, "correct stderr count");
+	} else {
+		libst_failed (test, "wrong stderr count %i", stderr_count);
+	}
+
+	/************************************************************/
+	libst_title (test, "make sure run correct helper, and kill it");
+	mexitcode = -1;
+	ret = pk_spawn_command (spawn, "./pk-spawn-test.sh");
+	if (ret == TRUE) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "did not run helper");
+	}
+
+	g_timeout_add_seconds (1, cancel_cb, spawn);
+	/* spin for a bit, todo add timer to break out if we fail */
 	loop = g_main_loop_new (NULL, FALSE);
 	g_main_loop_run (loop);
+
+	/************************************************************/
+	libst_title (test, "make sure finished broken");
+	if (mexitcode == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "finish %i!", mexitcode);
+	}
 #endif
 
 	g_object_unref (spawn);



More information about the PackageKit mailing list