Merge lp:~mikemc/ubuntuone-control-panel/fix-credentials-race into lp:ubuntuone-control-panel

Proposed by Mike McCracken on 2012-08-30
Status: Merged
Approved by: Roberto Alsina on 2012-08-30
Approved revision: 355
Merged at revision: 353
Proposed branch: lp:~mikemc/ubuntuone-control-panel/fix-credentials-race
Merge into: lp:ubuntuone-control-panel
Diff against target: 75 lines (+37/-3)
2 files modified
ubuntuone/controlpanel/backend.py (+11/-3)
ubuntuone/controlpanel/tests/test_backend.py (+26/-0)
To merge this branch: bzr merge lp:~mikemc/ubuntuone-control-panel/fix-credentials-race
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve on 2012-08-30
Manuel de la Peña (community) 2012-08-30 Approve on 2012-08-30
Review via email: mp+121969@code.launchpad.net

Commit Message

- Fix race in backend get_credentials call. (LP: #1042860)

Description of the Change

- Fix race in backend get_credentials call. (LP: #1042860)

To post a comment you must log in.
Manuel de la Peña (mandel) wrote :

I wonder why we did not see this before..

review: Approve
Roberto Alsina (ralsina) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/controlpanel/backend.py'
2--- ubuntuone/controlpanel/backend.py 2012-08-27 15:11:37 +0000
3+++ ubuntuone/controlpanel/backend.py 2012-08-30 00:24:17 +0000
4@@ -23,7 +23,9 @@
5 from collections import defaultdict
6 from functools import wraps
7
8-from twisted.internet.defer import inlineCallbacks, returnValue
9+from twisted.internet.defer import (inlineCallbacks,
10+ returnValue,
11+ DeferredLock)
12 from ubuntuone.platform.credentials import CredentialsManagementTool
13
14 from ubuntuone.controlpanel import sd_client, replication_client
15@@ -124,6 +126,8 @@
16 UPLOAD_KEY: -1, # no limit
17 }
18
19+ credentials_lock = DeferredLock()
20+
21 def __init__(self, shutdown_func=None):
22 """Initialize the web_client."""
23 self._status_changed_handler = None
24@@ -323,8 +327,12 @@
25 @inlineCallbacks
26 def get_credentials(self):
27 """Find credentials."""
28- if not self._credentials:
29- self._credentials = yield self.login_client.find_credentials()
30+ yield self.credentials_lock.acquire()
31+ try:
32+ if not self._credentials:
33+ self._credentials = yield self.login_client.find_credentials()
34+ finally:
35+ self.credentials_lock.release()
36 returnValue(self._credentials)
37
38 @inlineCallbacks
39
40=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
41--- ubuntuone/controlpanel/tests/test_backend.py 2012-08-27 15:00:01 +0000
42+++ ubuntuone/controlpanel/tests/test_backend.py 2012-08-30 00:24:17 +0000
43@@ -524,6 +524,32 @@
44 self.assertEqual(self.be.login_client._called['find_credentials'], 1)
45
46 @inlineCallbacks
47+ def test_credentials_are_cached_slow(self):
48+ """The credentials are still cached when find_credentials is slow."""
49+ dq = defer.DeferredQueue()
50+
51+ @inlineCallbacks
52+ def delayed_find_creds():
53+ """Function with externally controlled return time."""
54+ fake_creds = yield dq.get()
55+ defer.returnValue(fake_creds)
56+
57+ self.patch(self.be.login_client, 'find_credentials',
58+ delayed_find_creds)
59+
60+ # Ensure that the second call to get_credentials occurs before
61+ # the first one gets a result from find_credentials by leaving
62+ # the queue empty until both are called:
63+
64+ d1 = self.be.get_credentials()
65+ d2 = self.be.get_credentials()
66+ dq.put("Blizzard")
67+ dq.put("Dilly Bar")
68+ creds1 = yield d1
69+ creds2 = yield d2
70+ self.assertEqual(creds1, creds2)
71+
72+ @inlineCallbacks
73 def test_clear_credentials(self):
74 """The credentials can be cleared."""
75 # ensure we have creds

Subscribers

People subscribed via source and target branches