Merge lp:~mvo/ubuntu-sso-client/lp711413 into lp:ubuntu-sso-client

Proposed by Michael Vogt
Status: Rejected
Rejected by: dobey
Proposed branch: lp:~mvo/ubuntu-sso-client/lp711413
Merge into: lp:ubuntu-sso-client
Diff against target: 126 lines (+98/-1)
2 files modified
ubuntu_sso/main/linux.py (+21/-1)
ubuntu_sso/main/tests/test_linux.py (+77/-0)
To merge this branch: bzr merge lp:~mvo/ubuntu-sso-client/lp711413
Reviewer Review Type Date Requested Status
dobey (community) Disapprove
Natalia Bidart Pending
Review via email: mp+107053@code.launchpad.net

Description of the change

This is one way of hopefully solving bug #711413 that shows up on errors.ubuntu.com currntly (via its duplicate #926678).

The idea is that if its a race on logout when the dbus session daemon gets killed before the syncdaemon, we can simply retry to access the dbus daemon until ubuntu-sso-client is also killed by the session logout (this branch assumes that this is the case). Its not entirely clear if it is - but the patch should not make anything worse, the worst outcome would be that it just dosn't fix anything in which case it should be reverted and the approach needs to be rethought.

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

Please don't add a new dependency on python-mock here. Instead, you should use BaseTestCase from ubuntu_sso.main.tests.linux and use self.patch() inside a test to patch a method, rather than using the @patch decorator from mock. You can see some usage of self.patch() in test_clients.py in the same directory.

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

On Wed, May 23, 2012 at 04:54:22PM -0000, Rodney Dawes wrote:
> Review: Needs Fixing
>
> Please don't add a new dependency on python-mock here. Instead, you should use BaseTestCase from ubuntu_sso.main.tests.linux and use self.patch() inside a test to patch a method, rather than using the @patch decorator from mock. You can see some usage of self.patch() in test_clients.py in the same directory.

Thanks, I agree with your point! Unfortunately I didn't had time to
update it yet and the recent feedback I got from seb128 about session
shutdown makes me uncertain that the fix is actually sufficient. I
wonder if we could do a experiment and push it to -proposed as it is
(should do no harm, famous last words ;) and see if the new version
number appears on errors.ubuntu.com, if so, the patch is not
sufficient and the whole branch can die. If its not showing up we have
some indication that its the right approach and that more work on it
is justified (and I will be happy to do it). What do you think?

Revision history for this message
dobey (dobey) wrote :

I don't think that is a sufficient test, and I don't like the idea of using -proposed as a means of discovering whether or not a bug is fixed by a change. What happens if it is uploaded, and nobody installs it, because all the people hitting the bug, do not have -proposed enabled? It won't appear, but doesn't mean this is the fix or the right approach to fixing it, either.

Is there a better way to have people test this, who are actually hitting the bug? Is there a reasonable way to duplicate the issue directly in a simple unit test case?

Revision history for this message
dobey (dobey) wrote :

Rejecting this as we have landed a better workaround for this issue in trunk already.

review: Disapprove

Unmerged revisions

958. By Michael Vogt

try to fix #711413 via a retry approach if the session bus is not available, the idea is that ubuntu-sso-client gets killed on logout hopefully before the retry-timeout is reached

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntu_sso/main/linux.py'
2--- ubuntu_sso/main/linux.py 2012-04-10 10:43:48 +0000
3+++ ubuntu_sso/main/linux.py 2012-05-23 15:49:21 +0000
4@@ -39,6 +39,7 @@
5 """
6
7 import signal
8+import time
9
10 import dbus
11 import dbus.service
12@@ -340,12 +341,31 @@
13 class UbuntuSSOProxy(object):
14 """Object that exposes the diff referenceable objects."""
15
16+ # the time and retry count to wait for the session bus to become
17+ # available before the system errors out
18+ DBUS_RETRY_WAIT_TIME = 0.2
19+ DBUS_RETRY_COUNT_MAX = 10
20+
21 def __init__(self, root):
22 self.root = root
23- self.bus = dbus.SessionBus()
24+ self.bus = self._get_session_bus_with_retry()
25 self.sso_login = None
26 self.cred_manager = None
27
28+ def _get_session_bus_with_retry(self):
29+ # keep retrying to avoid race on login/logout, see LP: #711413
30+ for i in range(self.DBUS_RETRY_COUNT_MAX):
31+ try:
32+ bus = dbus.SessionBus()
33+ break
34+ except dbus.DBusException:
35+ logger.exception("Failed to get the session dbus""")
36+ time.sleep(self.DBUS_RETRY_WAIT_TIME)
37+ else:
38+ # if we reach this point, we couldn't get a bus, so give up
39+ raise
40+ return bus
41+
42 def start(self):
43 """Start listening, nothing async to be done in this platform."""
44 # Register DBus service for making sure we run only one instance
45
46=== added file 'ubuntu_sso/main/tests/test_linux.py'
47--- ubuntu_sso/main/tests/test_linux.py 1970-01-01 00:00:00 +0000
48+++ ubuntu_sso/main/tests/test_linux.py 2012-05-23 15:49:21 +0000
49@@ -0,0 +1,77 @@
50+# -*- coding: utf-8 -*-
51+#
52+# Copyright 2012 Canonical Ltd.
53+#
54+# This program is free software: you can redistribute it and/or modify it
55+# under the terms of the GNU General Public License version 3, as published
56+# by the Free Software Foundation.
57+#
58+# This program is distributed in the hope that it will be useful, but
59+# WITHOUT ANY WARRANTY; without even the implied warranties of
60+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
61+# PURPOSE. See the GNU General Public License for more details.
62+#
63+# You should have received a copy of the GNU General Public License along
64+# with this program. If not, see <http://www.gnu.org/licenses/>.
65+#
66+# In addition, as a special exception, the copyright holders give
67+# permission to link the code of portions of this program with the
68+# OpenSSL library under certain conditions as described in each
69+# individual source file, and distribute linked combinations
70+# including the two.
71+# You must obey the GNU General Public License in all respects
72+# for all of the code used other than OpenSSL. If you modify
73+# file(s) with this exception, you may extend this exception to your
74+# version of the file(s), but you are not obligated to do so. If you
75+# do not wish to do so, delete this exception statement from your
76+# version. If you delete this exception statement from all source
77+# files in the program, then also delete it here.
78+"""Linux specific tests for the main module."""
79+
80+import time
81+
82+from mock import patch
83+
84+import dbus
85+
86+from ubuntu_sso.tests import TestCase
87+from ubuntu_sso.main import UbuntuSSOProxy
88+
89+# because we are using twisted we have java like names C0103
90+# pylint: disable=C0103
91+
92+
93+class UbuntuSSOProxyTestCase(TestCase):
94+ """Tests for the UbuntuSSOProxy """
95+
96+
97+ def test_retry_on_race_lp711413(self):
98+ """Test the retry on dbus failure feature to fix bug #711413 """
99+ def _simulate_dbus_unavailable_once():
100+ """ helper to simulate a dbus not-yet-ready error once """
101+ patcher.stop()
102+ raise dbus.DBusException()
103+ # simulate that the session bus is unavailable initially
104+ patcher = patch("dbus.SessionBus")
105+ session_bus_mock = patcher.start()
106+ session_bus_mock.side_effect = _simulate_dbus_unavailable_once
107+ # get proxy and measure the time to access the bus
108+ now = time.time()
109+ proxy = UbuntuSSOProxy(None)
110+ bus = proxy.bus
111+ delay = time.time() - now
112+ # verify that we have a bus and that it took the expected time
113+ self.assertNotEqual(bus, None)
114+ self.assertTrue(delay > 1*proxy.DBUS_RETRY_WAIT_TIME and
115+ delay < 2*proxy.DBUS_RETRY_WAIT_TIME)
116+
117+
118+ @patch("time.sleep")
119+ @patch("dbus.SessionBus")
120+ def test_raise_on_timeout(self, mock_session_bus, mock_sleep):
121+ """Test that the normal dbus.DBusException is raised on timeout """
122+ def _raise_dbus_exception():
123+ raise dbus.DBusException()
124+ mock_session_bus.side_effect = _raise_dbus_exception
125+ self.assertRaises(dbus.DBusException, UbuntuSSOProxy, None)
126+

Subscribers

People subscribed via source and target branches