Merge lp:~larryprice/libertine/listmodel-crash into lp:libertine
- listmodel-crash
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Christopher Townsend | ||||
Approved revision: | 274 | ||||
Merged at revision: | 287 | ||||
Proposed branch: | lp:~larryprice/libertine/listmodel-crash | ||||
Merge into: | lp:libertine | ||||
Diff against target: |
173 lines (+28/-23) 6 files modified
libertine/ContainerAppsList.cpp (+2/-7) libertine/ContainerAppsList.h (+2/-1) libertine/ContainerArchivesList.cpp (+2/-7) libertine/ContainerArchivesList.h (+2/-1) libertine/qml/ContainersView.qml (+16/-6) python/libertine/ChrootContainer.py (+4/-1) |
||||
To merge this branch: | bzr merge lp:~larryprice/libertine/listmodel-crash | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Libertine CI Bot | continuous-integration | Approve | |
Christopher Townsend (community) | Approve | ||
Review via email: mp+302854@code.launchpad.net |
Commit message
Return user to homepage when container has been destroyed from under them.
Description of the change
Return user to homepage when container has been destroyed from under them.
Also check our listmodels for null before trying to call methods on them, especially from noexcept methods (:
Libertine CI Bot (libertine-ci-bot) wrote : | # |
Christopher Townsend (townsend) wrote : | # |
Works well and no more crash.
Just one inline comment.
Thanks!
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:274
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Christopher Townsend (townsend) wrote : | # |
Ok, looks good. Thanks!
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Libertine CI Bot (libertine-ci-bot) : | # |
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Autolanding.
Approved revid is not set in launchpad. This is most likely a launchpad issue and re-approve should fix it. There is also a chance (although a very small one) this is a permission problem of the ps-jenkins bot.
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Libertine CI Bot (libertine-ci-bot) : | # |
Preview Diff
1 | === modified file 'libertine/ContainerAppsList.cpp' | |||
2 | --- libertine/ContainerAppsList.cpp 2016-03-24 14:15:26 +0000 | |||
3 | +++ libertine/ContainerAppsList.cpp 2016-08-15 16:00:34 +0000 | |||
4 | @@ -27,11 +27,6 @@ | |||
5 | 27 | { } | 27 | { } |
6 | 28 | 28 | ||
7 | 29 | 29 | ||
8 | 30 | ContainerAppsList:: | ||
9 | 31 | ~ContainerAppsList() | ||
10 | 32 | { } | ||
11 | 33 | |||
12 | 34 | |||
13 | 35 | void ContainerAppsList:: | 30 | void ContainerAppsList:: |
14 | 36 | setContainerApps(QString const& container_id) | 31 | setContainerApps(QString const& container_id) |
15 | 37 | { | 32 | { |
16 | @@ -51,12 +46,12 @@ | |||
17 | 51 | 46 | ||
18 | 52 | bool ContainerAppsList:: | 47 | bool ContainerAppsList:: |
19 | 53 | empty() const noexcept | 48 | empty() const noexcept |
21 | 54 | { return apps_->empty(); } | 49 | { return apps_ == nullptr || apps_->empty(); } |
22 | 55 | 50 | ||
23 | 56 | 51 | ||
24 | 57 | ContainerAppsList::size_type ContainerAppsList:: | 52 | ContainerAppsList::size_type ContainerAppsList:: |
25 | 58 | size() const noexcept | 53 | size() const noexcept |
27 | 59 | { return apps_->count(); } | 54 | { return apps_ != nullptr ? apps_->count() : 0;} |
28 | 60 | 55 | ||
29 | 61 | 56 | ||
30 | 62 | int ContainerAppsList:: | 57 | int ContainerAppsList:: |
31 | 63 | 58 | ||
32 | === modified file 'libertine/ContainerAppsList.h' | |||
33 | --- libertine/ContainerAppsList.h 2016-03-24 14:15:26 +0000 | |||
34 | +++ libertine/ContainerAppsList.h 2016-08-15 16:00:34 +0000 | |||
35 | @@ -53,7 +53,8 @@ | |||
36 | 53 | ContainerAppsList(ContainerConfigList* container_config_list, | 53 | ContainerAppsList(ContainerConfigList* container_config_list, |
37 | 54 | QObject* parent = nullptr); | 54 | QObject* parent = nullptr); |
38 | 55 | 55 | ||
40 | 56 | ~ContainerAppsList(); | 56 | virtual |
41 | 57 | ~ContainerAppsList() = default; | ||
42 | 57 | 58 | ||
43 | 58 | Q_INVOKABLE void | 59 | Q_INVOKABLE void |
44 | 59 | setContainerApps(QString const& container_id); | 60 | setContainerApps(QString const& container_id); |
45 | 60 | 61 | ||
46 | === modified file 'libertine/ContainerArchivesList.cpp' | |||
47 | --- libertine/ContainerArchivesList.cpp 2016-03-10 21:33:25 +0000 | |||
48 | +++ libertine/ContainerArchivesList.cpp 2016-08-15 16:00:34 +0000 | |||
49 | @@ -27,11 +27,6 @@ | |||
50 | 27 | { } | 27 | { } |
51 | 28 | 28 | ||
52 | 29 | 29 | ||
53 | 30 | ContainerArchivesList:: | ||
54 | 31 | ~ContainerArchivesList() | ||
55 | 32 | { } | ||
56 | 33 | |||
57 | 34 | |||
58 | 35 | void ContainerArchivesList:: | 30 | void ContainerArchivesList:: |
59 | 36 | setContainerArchives(QString const& container_id) | 31 | setContainerArchives(QString const& container_id) |
60 | 37 | { | 32 | { |
61 | @@ -44,12 +39,12 @@ | |||
62 | 44 | 39 | ||
63 | 45 | bool ContainerArchivesList:: | 40 | bool ContainerArchivesList:: |
64 | 46 | empty() const noexcept | 41 | empty() const noexcept |
66 | 47 | { return archives_->empty(); } | 42 | { return archives_ == nullptr || archives_->empty(); } |
67 | 48 | 43 | ||
68 | 49 | 44 | ||
69 | 50 | ContainerArchivesList::size_type ContainerArchivesList:: | 45 | ContainerArchivesList::size_type ContainerArchivesList:: |
70 | 51 | size() const noexcept | 46 | size() const noexcept |
72 | 52 | { return archives_->count(); } | 47 | { return archives_ != nullptr ? archives_->count() : 0; } |
73 | 53 | 48 | ||
74 | 54 | 49 | ||
75 | 55 | int ContainerArchivesList:: | 50 | int ContainerArchivesList:: |
76 | 56 | 51 | ||
77 | === modified file 'libertine/ContainerArchivesList.h' | |||
78 | --- libertine/ContainerArchivesList.h 2016-03-10 21:33:25 +0000 | |||
79 | +++ libertine/ContainerArchivesList.h 2016-08-15 16:00:34 +0000 | |||
80 | @@ -53,7 +53,8 @@ | |||
81 | 53 | ContainerArchivesList(ContainerConfigList* container_config_list, | 53 | ContainerArchivesList(ContainerConfigList* container_config_list, |
82 | 54 | QObject* parent = nullptr); | 54 | QObject* parent = nullptr); |
83 | 55 | 55 | ||
85 | 56 | ~ContainerArchivesList(); | 56 | virtual |
86 | 57 | ~ContainerArchivesList() = default; | ||
87 | 57 | 58 | ||
88 | 58 | Q_INVOKABLE void | 59 | Q_INVOKABLE void |
89 | 59 | setContainerArchives(QString const& container_id); | 60 | setContainerArchives(QString const& container_id); |
90 | 60 | 61 | ||
91 | === modified file 'libertine/qml/ContainersView.qml' | |||
92 | --- libertine/qml/ContainersView.qml 2016-07-15 18:39:58 +0000 | |||
93 | +++ libertine/qml/ContainersView.qml 2016-08-15 16:00:34 +0000 | |||
94 | @@ -55,8 +55,12 @@ | |||
95 | 55 | } | 55 | } |
96 | 56 | model: containerConfigList | 56 | model: containerConfigList |
97 | 57 | 57 | ||
100 | 58 | function edit(containerId) { | 58 | function edit(id, status) { |
101 | 59 | mainView.currentContainer = containerId | 59 | if (status === "removing") { |
102 | 60 | mainView.error(i18n.tr("Container Unavailable"), i18n.tr("Container is being destroyed and is no longer editable.")) | ||
103 | 61 | return | ||
104 | 62 | } | ||
105 | 63 | mainView.currentContainer = id | ||
106 | 60 | containerAppsList.setContainerApps(mainView.currentContainer) | 64 | containerAppsList.setContainerApps(mainView.currentContainer) |
107 | 61 | pageStack.push(Qt.resolvedUrl("HomeView.qml"), {"currentContainer": mainView.currentContainer}) | 65 | pageStack.push(Qt.resolvedUrl("HomeView.qml"), {"currentContainer": mainView.currentContainer}) |
108 | 62 | } | 66 | } |
109 | @@ -82,7 +86,7 @@ | |||
110 | 82 | running: containerActivity.visible | 86 | running: containerActivity.visible |
111 | 83 | } | 87 | } |
112 | 84 | 88 | ||
114 | 85 | onClicked: { containersList.edit(containerId) } | 89 | onClicked: { containersList.edit(containerId, installStatus) } |
115 | 86 | 90 | ||
116 | 87 | leadingActions: ListItemActions { | 91 | leadingActions: ListItemActions { |
117 | 88 | actions: [ | 92 | actions: [ |
118 | @@ -92,8 +96,8 @@ | |||
119 | 92 | description: i18n.tr("Delete Container") | 96 | description: i18n.tr("Delete Container") |
120 | 93 | onTriggered: { | 97 | onTriggered: { |
121 | 94 | var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView) | 98 | var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView) |
122 | 99 | worker.error.connect(mainView.error) | ||
123 | 95 | worker.destroyContainer(containerId) | 100 | worker.destroyContainer(containerId) |
124 | 96 | mainView.currentContainer = containerId | ||
125 | 97 | } | 101 | } |
126 | 98 | } | 102 | } |
127 | 99 | ] | 103 | ] |
128 | @@ -117,7 +121,7 @@ | |||
129 | 117 | visible: (installStatus === i18n.tr("ready") || | 121 | visible: (installStatus === i18n.tr("ready") || |
130 | 118 | installStatus === i18n.tr("updating")) ? true : false | 122 | installStatus === i18n.tr("updating")) ? true : false |
131 | 119 | onTriggered: { | 123 | onTriggered: { |
133 | 120 | containersList.edit(containerId) | 124 | containersList.edit(containerId, installStatus) |
134 | 121 | } | 125 | } |
135 | 122 | } | 126 | } |
136 | 123 | ] | 127 | ] |
137 | @@ -128,13 +132,19 @@ | |||
138 | 128 | Component.onCompleted: { | 132 | Component.onCompleted: { |
139 | 129 | containerConfigList.configChanged.connect(updateContainerList) | 133 | containerConfigList.configChanged.connect(updateContainerList) |
140 | 130 | } | 134 | } |
142 | 131 | 135 | ||
143 | 132 | Component.onDestruction: { | 136 | Component.onDestruction: { |
144 | 133 | containerConfigList.configChanged.disconnect(updateContainerList) | 137 | containerConfigList.configChanged.disconnect(updateContainerList) |
145 | 134 | } | 138 | } |
146 | 135 | 139 | ||
147 | 136 | function updateContainerList() { | 140 | function updateContainerList() { |
148 | 137 | containerConfigList.reloadContainerList() | 141 | containerConfigList.reloadContainerList() |
149 | 142 | |||
150 | 143 | if (mainView.currentContainer && !containerConfigList.getContainerStatus(mainView.currentContainer) && pageStack.currentPage !== containersView) { | ||
151 | 144 | pageStack.pop() | ||
152 | 145 | mainView.currentContainer = "" | ||
153 | 146 | mainView.error(i18n.tr("Container Unavailable"), i18n.tr("This container has been destroyed and is no longer valid. You have been returned to the containers overview.")) | ||
154 | 147 | } | ||
155 | 138 | } | 148 | } |
156 | 139 | 149 | ||
157 | 140 | function showPasswordDialog(enableMultiarch, containerName) { | 150 | function showPasswordDialog(enableMultiarch, containerName) { |
158 | 141 | 151 | ||
159 | === modified file 'python/libertine/ChrootContainer.py' | |||
160 | --- python/libertine/ChrootContainer.py 2016-08-09 13:58:26 +0000 | |||
161 | +++ python/libertine/ChrootContainer.py 2016-08-15 16:00:34 +0000 | |||
162 | @@ -61,7 +61,10 @@ | |||
163 | 61 | 61 | ||
164 | 62 | def destroy_libertine_container(self): | 62 | def destroy_libertine_container(self): |
165 | 63 | container_root = os.path.join(utils.get_libertine_containers_dir_path(), self.container_id) | 63 | container_root = os.path.join(utils.get_libertine_containers_dir_path(), self.container_id) |
167 | 64 | shutil.rmtree(container_root) | 64 | try: |
168 | 65 | shutil.rmtree(container_root) | ||
169 | 66 | except Exception as e: | ||
170 | 67 | print("%s" % e) | ||
171 | 65 | 68 | ||
172 | 66 | def create_libertine_container(self, password=None, multiarch=False, verbosity=1): | 69 | def create_libertine_container(self, password=None, multiarch=False, verbosity=1): |
173 | 67 | # Create the actual chroot | 70 | # Create the actual chroot |
PASSED: Continuous integration, rev:273 /jenkins. canonical. com/libertine/ job/lp- libertine- ci/98/ /jenkins. canonical. com/libertine/ job/build/ 283 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= vivid+overlay, testname= default/ 233 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= xenial+ overlay, testname= default/ 233 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= yakkety, testname= default/ 233 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= vivid+overlay, testname= default/ 233 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= xenial+ overlay, testname= default/ 233 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= yakkety, testname= default/ 233 /jenkins. canonical. com/libertine/ job/lp- generic- update- mp/215/ console /jenkins. canonical. com/libertine/ job/build- 0-fetch/ 285 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= vivid+overlay/ 269 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= xenial+ overlay/ 269 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= yakkety/ 269 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= vivid+overlay/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= vivid+overlay/ 262/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 262/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= yakkety/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= yakkety/ 262/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= vivid+overlay/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= vivid+overlay/ 262/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 262/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= yakkety/ 262 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= yakkety/ 262/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/libertine/ job/lp- libertine- ci/98/rebuild
https:/