Merge lp:~mvo/click/lp1232130-kill-on-remove-2 into lp:click/devel

Proposed by Michael Vogt
Status: Merged
Approved by: Michael Vogt
Approved revision: 437
Merged at revision: 559
Proposed branch: lp:~mvo/click/lp1232130-kill-on-remove-2
Merge into: lp:click/devel
Diff against target: 232 lines (+99/-35)
4 files modified
click/tests/helpers.py (+21/-0)
click/tests/test_user.py (+22/-8)
lib/click/user.vala (+48/-27)
pk-plugin/pk-plugin-click.c (+8/-0)
To merge this branch: bzr merge lp:~mvo/click/lp1232130-kill-on-remove-2
Reviewer Review Type Date Requested Status
Barry Warsaw Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+237601@code.launchpad.net

Commit message

When uninstalling a app, stop it if its running.

Description of the change

This branch stops running applications when a click package gets removed. The previous branch did not work because the ubuntu-app-stop command needs access to the session bus to work but click/PK run in a different context. Fortunately the users session bus address is available in /run/user which this branch uses now.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:437
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~mvo/click/lp1232130-kill-on-remove-2/+merge/237601/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/click-devel-ci/92/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/click-devel-utopic-amd64-ci/94
    SUCCESS: http://jenkins.qa.ubuntu.com/job/click-devel-utopic-armhf-ci/92
        deb: http://jenkins.qa.ubuntu.com/job/click-devel-utopic-armhf-ci/92/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/click-devel-utopic-i386-ci/92

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/click-devel-ci/92/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Barry Warsaw (barry) wrote :

One minor comment, but otherwise LGTM.

review: Approve
Revision history for this message
Michael Vogt (mvo) wrote :

On Tue, Feb 17, 2015 at 04:15:44PM -0000, Barry Warsaw wrote:
> Review: Approve
>
> One minor comment, but otherwise LGTM.

Thanks for the review!

[..]
> > +class StopAppTestCase(TestCase):
> > +
> > + def setUp(self):
> > + super(StopAppTestCase, self).setUp()
>
> I forget, does click still have to be Python 2 compatible? If not, then:
>
> super().setUp()
>
> because magic!

Woah, thats cool. I will keep that in mind :) We currently still
support py2.7 unfortunately. Might be worth reconsidering - but not
for this one line :)

Cheers,
 Michael

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'click/tests/helpers.py'
--- click/tests/helpers.py 2014-09-29 13:23:52 +0000
+++ click/tests/helpers.py 2014-10-08 14:13:24 +0000
@@ -30,6 +30,7 @@
3030
31import contextlib31import contextlib
32from functools import wraps32from functools import wraps
33import json
33import os34import os
34import re35import re
35import shutil36import shutil
@@ -59,6 +60,26 @@
59 return wrapper60 return wrapper
6061
6162
63def make_installed_click(db, db_dir, package="test-1", version="1.0",
64 json_data={}, make_current=True, user="@all"):
65 """Create a fake installed click package for the given db/db_dir"""
66 json_data["name"] = package
67 json_data["version"] = version
68 with mkfile_utf8(os.path.join(
69 db_dir, package, version, ".click", "info",
70 "%s.manifest" % package)) as f:
71 json.dump(json_data, f, ensure_ascii=False)
72 if make_current:
73 os.symlink(
74 version, os.path.join(db_dir, package, "current"))
75 if user == "@all":
76 registry = Click.User.for_all_users(db)
77 else:
78 registry = Click.User.for_user(db, user)
79 registry.set_version(package, version)
80 return os.path.join(db_dir, package, version)
81
82
62class TestCase(gimock.GIMockTestCase):83class TestCase(gimock.GIMockTestCase):
63 def setUp(self):84 def setUp(self):
64 super(TestCase, self).setUp()85 super(TestCase, self).setUp()
6586
=== modified file 'click/tests/test_user.py'
--- click/tests/test_user.py 2014-09-29 11:12:52 +0000
+++ click/tests/test_user.py 2014-10-08 14:13:24 +0000
@@ -34,6 +34,7 @@
34from click.tests.gimock_types import Passwd34from click.tests.gimock_types import Passwd
35from click.tests.helpers import (35from click.tests.helpers import (
36 TestCase,36 TestCase,
37 make_installed_click,
37 mkfile,38 mkfile,
38 make_file_with_content,39 make_file_with_content,
39 touch,40 touch,
@@ -557,21 +558,34 @@
557 self.assertEqual(b_overlay, registry.get_path("b"))558 self.assertEqual(b_overlay, registry.get_path("b"))
558 self.assertTrue(registry.is_removable("b"))559 self.assertTrue(registry.is_removable("b"))
559560
560 def test_app_stops_on_remove(self):561
562class StopAppTestCase(TestCase):
563
564 def setUp(self):
565 super(StopAppTestCase, self).setUp()
566 self.use_temp_dir()
567 self.db = Click.DB()
568 self.db.add(self.temp_dir)
569
570 # setup fake app_stop
561 fake_app_stop = os.path.join(self.temp_dir, "bin", "ubuntu-app-stop")571 fake_app_stop = os.path.join(self.temp_dir, "bin", "ubuntu-app-stop")
562 fake_app_stop_output = os.path.join(self.temp_dir, "fake-app-stop.out")572 self.fake_app_stop_output = os.path.join(
573 self.temp_dir, "fake-app-stop.out")
563 fake_app_stop_content = dedent("""\574 fake_app_stop_content = dedent("""\
564 #!/bin/sh575 #!/bin/sh
565 echo "$@" >> %s576 echo "$@" >> %s
566 """ % fake_app_stop_output)577 """ % self.fake_app_stop_output)
567 make_file_with_content(fake_app_stop, fake_app_stop_content, 0o755)578 make_file_with_content(fake_app_stop, fake_app_stop_content, 0o755)
568 # its ok to modify env here, click.helpers.TestCase will take care579 # its ok to modify env here, click.helpers.TestCase will take care
569 # of it580 # of it
570 os.environ["PATH"] = "%s:%s" % (581 os.environ["PATH"] = "%s:%s" % (
571 os.path.dirname(fake_app_stop), os.environ["PATH"])582 os.path.dirname(fake_app_stop), os.environ["PATH"])
572 # get a app with manifest etc all583
573 _, registry = self._setUpMultiDB()584 def test_app_stops_on_remove(self):
574 registry.remove("a")585 make_installed_click(self.db, self.temp_dir, "meep", "2.0",
586 {"hooks": {"a-app": {}}})
587 registry = Click.User.for_user(self.db, "user")
588 registry.remove("meep")
575 # ensure that stop was called with the right app589 # ensure that stop was called with the right app
576 with open(fake_app_stop_output) as f:590 with open(self.fake_app_stop_output) as f:
577 self.assertEqual("a_a-app_1.1", f.read().strip())591 self.assertEqual("meep_a-app_2.0", f.read().strip())
578592
=== modified file 'lib/click/user.vala'
--- lib/click/user.vala 2014-09-29 13:23:12 +0000
+++ lib/click/user.vala 2014-10-08 14:13:24 +0000
@@ -598,8 +598,49 @@
598 old_version, version, name);598 old_version, version, name);
599 }599 }
600600
601 private bool601 private string
602 stop_running_app (string package, string version)602 get_dbus_session_bus_env_for_current_user()
603 {
604 string euid = "%i".printf((int)(Posix.geteuid ()));
605 var dbus_session_file = Path.build_filename(
606 "/run", "user", euid, "dbus-session");
607 string session_env;
608 try {
609 FileUtils.get_contents(dbus_session_file, out session_env);
610 session_env = session_env.strip();
611 } catch (Error e) {
612 warning("Can not get the dbus session to stop app (%s)", e.message);
613 }
614 return session_env;
615 }
616
617 private bool
618 stop_single_app (string app_id)
619 {
620 // get the users dbus session when we run as root first as this
621 // is where ubuntu-app-stop listens
622 string[] envp = Environ.get();
623 envp += get_dbus_session_bus_env_for_current_user();
624
625 string[] command = {
626 "ubuntu-app-stop", app_id
627 };
628 bool res = false;
629 try {
630 int exit_status;
631 Process.spawn_sync
632 (null, command, envp,
633 SpawnFlags.SEARCH_PATH,
634 null, null, null, out exit_status);
635 res = Process.check_exit_status (exit_status);
636 } catch (Error e) {
637 res = false;
638 }
639 return res;
640 }
641
642 private bool
643 stop_running_apps_for_package (string package, string version)
603 {644 {
604 var res = true;645 var res = true;
605 if (! find_on_path ("ubuntu-app-stop"))646 if (! find_on_path ("ubuntu-app-stop"))
@@ -619,24 +660,7 @@
619 }660 }
620 var hooks = manifest.get_object_member ("hooks");661 var hooks = manifest.get_object_member ("hooks");
621 foreach (unowned string app_name in hooks.get_members ())662 foreach (unowned string app_name in hooks.get_members ())
622 {663 res &= stop_single_app (@"$(package)_$(app_name)_$(version)");
623 // FIXME: move this into a "stop_single_app" helper
624 string[] command = {
625 "ubuntu-app-stop",
626 @"$(package)_$(app_name)_$(version)"
627 };
628 try {
629 int exit_status;
630 Process.spawn_sync
631 (null, command, null,
632 SpawnFlags.SEARCH_PATH |
633 SpawnFlags.STDOUT_TO_DEV_NULL,
634 null, null, null, out exit_status);
635 res &= Process.check_exit_status (exit_status);
636 } catch (Error e) {
637 res &= false;
638 }
639 }
640 return res;664 return res;
641 }665 }
642666
@@ -658,6 +682,8 @@
658 old_version = Path.get_basename (target);682 old_version = Path.get_basename (target);
659 drop_privileges ();683 drop_privileges ();
660 try {684 try {
685 // stop before removing the path to the manifest
686 stop_running_apps_for_package (package, old_version);
661 unlink_force (path);687 unlink_force (path);
662 } finally {688 } finally {
663 regain_privileges ();689 regain_privileges ();
@@ -673,19 +699,14 @@
673 ensure_db ();699 ensure_db ();
674 drop_privileges ();700 drop_privileges ();
675 try {701 try {
702 // stop before removing the path to the manifest
703 stop_running_apps_for_package (package, old_version);
676 symlink_force (HIDDEN_VERSION, path);704 symlink_force (HIDDEN_VERSION, path);
677 } finally {705 } finally {
678 regain_privileges ();706 regain_privileges ();
679 }707 }
680 }708 }
681709
682 drop_privileges ();
683 try {
684 stop_running_app (package, old_version);
685 } finally {
686 regain_privileges ();
687 }
688
689 if (! is_pseudo_user)710 if (! is_pseudo_user)
690 package_remove_hooks (db, package, old_version, name);711 package_remove_hooks (db, package, old_version, name);
691 }712 }
692713
=== modified file 'pk-plugin/pk-plugin-click.c'
--- pk-plugin/pk-plugin-click.c 2014-09-02 08:44:39 +0000
+++ pk-plugin/pk-plugin-click.c 2014-10-08 14:13:24 +0000
@@ -637,6 +637,11 @@
637 GError *error = NULL;637 GError *error = NULL;
638 gchar *summary = NULL;638 gchar *summary = NULL;
639639
640 // PK does not set a PATH, but we need one for removal
641 const gchar *old_path = g_getenv("PATH");
642 if(old_path == NULL)
643 g_setenv("PATH", DEFAULT_PATH, 0);
644
640 username = click_get_username_for_uid645 username = click_get_username_for_uid
641 (pk_transaction_get_uid (transaction));646 (pk_transaction_get_uid (transaction));
642 if (!username) {647 if (!username) {
@@ -701,6 +706,9 @@
701 ret = TRUE;706 ret = TRUE;
702707
703out:708out:
709 if(old_path == NULL)
710 g_unsetenv("PATH");
711
704 g_free (summary);712 g_free (summary);
705 if (error)713 if (error)
706 g_error_free (error);714 g_error_free (error);

Subscribers

People subscribed via source and target branches

to all changes: