Merge lp:~rbalint/update-manager/retry-after-failed-transaction into lp:update-manager

Proposed by Balint Reczey
Status: Merged
Merged at revision: 2836
Proposed branch: lp:~rbalint/update-manager/retry-after-failed-transaction
Merge into: lp:update-manager
Diff against target: 159 lines (+50/-14)
5 files modified
UpdateManager/Core/MyCache.py (+2/-0)
UpdateManager/UpdateManager.py (+2/-2)
UpdateManager/backend/InstallBackendAptdaemon.py (+9/-1)
UpdateManager/backend/__init__.py (+23/-11)
debian/changelog (+14/-0)
To merge this branch: bzr merge lp:~rbalint/update-manager/retry-after-failed-transaction
Reviewer Review Type Date Requested Status
Julian Andres Klode Approve
Brian Murray Pending
Review via email: mp+354648@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Balint Reczey (rbalint) wrote :

Since update-manager does not hold a lock unattended-upgrades can change installed packages behind its back and u-m gets a failed transaction due to holding an outdated cache.
The user is now notified about the problem and can try again.

Revision history for this message
Julian Andres Klode (juliank) wrote :

bug 1702083 is

  File "/usr/lib/python3/dist-packages/UpdateManager/Core/UpdateList.py", line 471, in update
    self.distUpgradeWouldDelete = cache.saveDistUpgrade()
AttributeError: 'NoneType' object has no attribute 'saveDistUpgrade'

I don't see how that's relevant here.

Revision history for this message
Balint Reczey (rbalint) wrote :

> bug 1702083 is
>
> File "/usr/lib/python3/dist-packages/UpdateManager/Core/UpdateList.py", line
> 471, in update
> self.distUpgradeWouldDelete = cache.saveDistUpgrade()
> AttributeError: 'NoneType' object has no attribute 'saveDistUpgrade'
>
> I don't see how that's relevant here.

Ah, yes, sorry, fixed to LP: #1791931

Revision history for this message
Julian Andres Klode (juliank) wrote :

Needs some fixing

review: Needs Fixing
2837. By Balint Reczey

Don't ask backend to do package operations aready done

Aptdaemon cancels the transaction when asked to remove packages already
removed which results the failure being shown to the user. This
is unnecessary as update-manager can just filter the package operations to
be done using a fresh cache and decrease the likelyhood of hitting
a race condition where packages to be removed are already removed.

LP: #1791931

2838. By Balint Reczey

Update changelog

Revision history for this message
Balint Reczey (rbalint) wrote :

> Needs some fixing

Thanks, fixed those.

Revision history for this message
Julian Andres Klode (juliank) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UpdateManager/Core/MyCache.py'
2--- UpdateManager/Core/MyCache.py 2018-03-18 21:43:58 +0000
3+++ UpdateManager/Core/MyCache.py 2018-09-11 14:59:42 +0000
4@@ -68,6 +68,8 @@
5
6 def __init__(self, progress, rootdir=None):
7 apt.Cache.__init__(self, progress, rootdir)
8+ # save for later
9+ self.rootdir = rootdir
10 # raise if we have packages in reqreinst state
11 # and let the caller deal with that (runs partial upgrade)
12 assert len(self.req_reinstall_pkgs) == 0
13
14=== modified file 'UpdateManager/UpdateManager.py'
15--- UpdateManager/UpdateManager.py 2018-06-08 06:35:03 +0000
16+++ UpdateManager/UpdateManager.py 2018-09-11 14:59:42 +0000
17@@ -272,8 +272,8 @@
18 return HWEUpgradeDialog(self)
19 return UpdatesAvailable(self, header, desc, need_reboot)
20
21- def start_error(self, is_update_error, header, desc):
22- if is_update_error:
23+ def start_error(self, update_and_retry, header, desc):
24+ if update_and_retry:
25 self._start_pane(UpdateErrorDialog(self, header, desc))
26 else:
27 self._start_pane(ErrorDialog(self, header, desc))
28
29=== modified file 'UpdateManager/backend/InstallBackendAptdaemon.py'
30--- UpdateManager/backend/InstallBackendAptdaemon.py 2018-03-26 12:33:11 +0000
31+++ UpdateManager/backend/InstallBackendAptdaemon.py 2018-09-11 14:59:42 +0000
32@@ -46,6 +46,7 @@
33 self.unity = UnitySupport()
34 self._expanded_size = None
35 self.button_cancel = None
36+ self.trans_failed_msg = None
37
38 def close(self):
39 if self.button_cancel:
40@@ -94,6 +95,8 @@
41 self._action_done(self.ACTION_INSTALL,
42 authorized=False, success=False,
43 error_string=None, error_desc=None)
44+ except errors.TransactionFailed as e:
45+ self.trans_failed_msg = str(e)
46 except dbus.DBusException as e:
47 #print(e, e.get_dbus_name())
48 if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply":
49@@ -223,15 +226,20 @@
50 def _on_finished(self, trans, status, action):
51 error_string = None
52 error_desc = None
53+ trans_failed = False
54 if status == EXIT_FAILED:
55 error_string = get_error_string_from_enum(trans.error.code)
56 error_desc = get_error_description_from_enum(trans.error.code)
57+ if self.trans_failed_msg:
58+ trans_failed = True
59+ error_desc = error_desc + "\n" + self.trans_failed_msg
60 # tell unity to hide the progress again
61 self.unity.set_progress(-1)
62 is_success = (status == EXIT_SUCCESS)
63 self._action_done(action,
64 authorized=True, success=is_success,
65- error_string=error_string, error_desc=error_desc)
66+ error_string=error_string, error_desc=error_desc,
67+ trans_failed=trans_failed)
68
69
70 if __name__ == "__main__":
71
72=== modified file 'UpdateManager/backend/__init__.py'
73--- UpdateManager/backend/__init__.py 2018-03-26 12:33:11 +0000
74+++ UpdateManager/backend/__init__.py 2018-09-11 14:59:42 +0000
75@@ -8,6 +8,7 @@
76
77 from gi.repository import GLib
78
79+from apt import Cache
80 import os
81
82 from UpdateManager.Core.utils import inhibit_sleep
83@@ -34,16 +35,26 @@
84 pkgs_install = []
85 pkgs_upgrade = []
86 pkgs_remove = []
87+ # Get a fresh cache in case update-manager's is outdated to
88+ # skip operations that already took place
89+ fresh_cache = Cache(rootdir=self.window_main.cache.rootdir)
90 for pkg in self.window_main.cache:
91- if pkg.marked_install:
92- pkgname = pkg.name
93- if pkg.is_auto_installed:
94- pkgname += "#auto"
95- pkgs_install.append(pkgname)
96- elif pkg.marked_upgrade:
97- pkgs_upgrade.append(pkg.name)
98- elif pkg.marked_delete:
99- pkgs_remove.append(pkg.name)
100+ try:
101+ if pkg.marked_install and \
102+ not fresh_cache[pkg.name].is_installed:
103+ pkgname = pkg.name
104+ if pkg.is_auto_installed:
105+ pkgname += "#auto"
106+ pkgs_install.append(pkgname)
107+ elif (pkg.marked_upgrade and
108+ fresh_cache[pkg.name].is_upgradable):
109+ pkgs_upgrade.append(pkg.name)
110+ elif (pkg.marked_delete and
111+ fresh_cache[pkg.name].is_installed):
112+ pkgs_remove.append(pkg.name)
113+ except KeyError:
114+ # pkg missing from fresh_cache can't be modified
115+ pass
116 self.commit(pkgs_install, pkgs_upgrade, pkgs_remove)
117 else:
118 self.update()
119@@ -57,7 +68,7 @@
120 raise NotImplemented
121
122 def _action_done(self, action, authorized, success, error_string,
123- error_desc):
124+ error_desc, trans_failed=False):
125
126 # If the progress dialog should be closed automatically afterwards
127 #settings = Gio.Settings.new("com.ubuntu.update-manager")
128@@ -70,7 +81,8 @@
129 if success:
130 self.window_main.start_available()
131 elif error_string:
132- self.window_main.start_error(False, error_string, error_desc)
133+ self.window_main.start_error(trans_failed, error_string,
134+ error_desc)
135 else:
136 # exit gracefuly, we can't just exit as this will trigger
137 # a crash if system.exit() is called in a exception handler
138
139=== modified file 'debian/changelog'
140--- debian/changelog 2018-09-06 07:10:42 +0000
141+++ debian/changelog 2018-09-11 14:59:42 +0000
142@@ -1,3 +1,17 @@
143+update-manager (1:18.10.8) UNRELEASED; urgency=medium
144+
145+ * Print transaction error and let the user try again applying updates
146+ (LP: #1317164)
147+ * Don't ask backend to do package operations aready done.
148+ Aptdaemon cancels the transaction when asked to remove packages already
149+ removed which results the failure being shown to the user. This
150+ is unnecessary as update-manager can just filter the package operations to
151+ be done using a fresh cache and decrease the likelyhood of hitting
152+ a race condition where packages to be removed are already removed.
153+ (LP: #1791931)
154+
155+ -- Balint Reczey <rbalint@ubuntu.com> Tue, 11 Sep 2018 13:40:57 +0200
156+
157 update-manager (1:18.10.7) cosmic; urgency=medium
158
159 * Fix PEP8 regression from 18.10.4 to allow autopkgtest to pass

Subscribers

People subscribed via source and target branches

to status/vote changes: