[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