Mir

Merge lp:~mir-team/mir/fix-1376324-0.8 into lp:mir/0.8

Proposed by Daniel van Vugt
Status: Merged
Approved by: Cemil Azizoglu
Approved revision: no longer in the source branch.
Merged at revision: 1969
Proposed branch: lp:~mir-team/mir/fix-1376324-0.8
Merge into: lp:mir/0.8
Diff against target: 368 lines (+186/-1)
16 files modified
CMakeLists.txt (+1/-1)
debian/changelog (+10/-0)
src/include/server/mir/compositor/buffer_stream.h (+1/-0)
src/server/compositor/buffer_bundle.h (+1/-0)
src/server/compositor/buffer_queue.cpp (+11/-0)
src/server/compositor/buffer_queue.h (+2/-0)
src/server/compositor/buffer_stream_surfaces.cpp (+5/-0)
src/server/compositor/buffer_stream_surfaces.h (+1/-0)
src/server/scene/basic_surface.cpp (+3/-0)
tests/include/mir_test_doubles/mock_buffer_bundle.h (+1/-0)
tests/include/mir_test_doubles/mock_buffer_stream.h (+1/-0)
tests/include/mir_test_doubles/stub_buffer_stream.h (+1/-0)
tests/integration-tests/CMakeLists.txt (+1/-0)
tests/integration-tests/surface_composition.cpp (+125/-0)
tests/integration-tests/test_exchange_buffer.cpp (+1/-0)
tests/unit-tests/compositor/test_buffer_queue.cpp (+21/-0)
To merge this branch: bzr merge lp:~mir-team/mir/fix-1376324-0.8
Reviewer Review Type Date Requested Status
Cemil Azizoglu (community) Approve
Robert Carr (community) Approve
Review via email: mp+246280@code.launchpad.net

Commit message

Backport fix for USC crash LP: #1376324

Description of the change

Because if you look closely, it's still crashing for RTM devices (Mir 0.8.0) that lack the fix:
https://errors.ubuntu.com/problem/bfb855ebc60f251bf495a2ffb24f2924c50bdbf8

Look closer again and you'll see evidence of vivid (Mir 0.9 devices) crashing too. But I think that's actually a different bug with the same basic signature -> bug 1401488 that only exists in 0.9 and later.

So in theory, this fix is all that's needed for 0.8 and RTM.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Yeah I know it's probably too late for 0.8.1 now we have a revision in QA already. This might be a good idea for 0.8.2 later though.

Discuss.

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Daniel, thanks for being on top of the bugs and raising. We'll try to convince product owners to land this.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

(Let's try this again)

Daniel, thanks for being on top of the bugs and bringing attention to this. We'll try to convince product owners to land it.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Daniel, I just noticed Saviq's silo has landed. So we should probably merge back the bot's changelog changes also.

Product owners have approved it. I'll probably put it in a silo tomorrow.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Cemil: The bot's changelog is grossly incorrect as mentioned in email.. And it makes me suspicious of what actually landed.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

BTW, I don't know where the silo landed too -- I haven't yet found any branch having been updated yet.

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Silo landed on RTM. As Saviq mentioned in an email, the train updates the changelog like that when the branch has never been used to land in RTM before. Up until Saviq's landing, it had been only used for ubuntu and then the source package was used to sync to rtm.

This will land in 0.8.2 (which means this branch needs to be updated with the correct PATCH version etc.).

Revision history for this message
Robert Carr (robertcarr) wrote :

looks ok to me. ABI looks unchanged.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

All tests passed. In the QA queue now.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Should we expect some script/robot/silo to land this or is manual intervention required?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-01-12 04:17:53 +0000
3+++ CMakeLists.txt 2015-01-15 03:19:37 +0000
4@@ -28,7 +28,7 @@
5
6 set(MIR_VERSION_MAJOR 0)
7 set(MIR_VERSION_MINOR 8) # This should change at least with every MIRSERVER_ABI
8-set(MIR_VERSION_PATCH 1)
9+set(MIR_VERSION_PATCH 2)
10
11 set(MIR_VERSION ${MIR_VERSION_MAJOR}.${MIR_VERSION_MINOR}.${MIR_VERSION_PATCH})
12
13
14=== modified file 'debian/changelog'
15--- debian/changelog 2015-01-15 03:13:20 +0000
16+++ debian/changelog 2015-01-15 03:19:37 +0000
17@@ -1,3 +1,13 @@
18+mir (0.8.2-0ubuntu1) UNRELEASED; urgency=medium
19+
20+ * Bug fix release 0.8.2 (https://launchpad.net/mir/+milestone/0.8.2)
21+ - ABIs all unchanged. No downstream projects need rebuilding.
22+ - Fixes bug: Crash in /usr/sbin/unity-system-compositor:*** Error in
23+ `unity-system-compositor': free(): invalid pointer: ADDR ***
24+ (LP: #1376324)
25+
26+ -- Daniel van Vugt <daniel.van.vugt@canonical.com> Thu, 15 Jan 2015 11:15:07 +0800
27+
28 mir (0.8.1+15.04.20150112.2~rtm-0ubuntu1) 14.09; urgency=medium
29
30 [ Daniel van Vugt ]
31
32=== modified file 'src/include/server/mir/compositor/buffer_stream.h'
33--- src/include/server/mir/compositor/buffer_stream.h 2014-09-11 05:51:44 +0000
34+++ src/include/server/mir/compositor/buffer_stream.h 2015-01-15 03:19:37 +0000
35@@ -54,6 +54,7 @@
36 virtual void force_requests_to_complete() = 0;
37 virtual int buffers_ready_for_compositor() const = 0;
38 virtual void drop_old_buffers() = 0;
39+ virtual void drop_client_requests() = 0;
40 };
41
42 }
43
44=== modified file 'src/server/compositor/buffer_bundle.h'
45--- src/server/compositor/buffer_bundle.h 2014-09-11 05:51:44 +0000
46+++ src/server/compositor/buffer_bundle.h 2015-01-15 03:19:37 +0000
47@@ -68,6 +68,7 @@
48 */
49 virtual int buffers_free_for_client() const = 0;
50 virtual void drop_old_buffers() = 0;
51+ virtual void drop_client_requests() = 0;
52
53 protected:
54 BufferBundle() = default;
55
56=== modified file 'src/server/compositor/buffer_queue.cpp'
57--- src/server/compositor/buffer_queue.cpp 2014-09-30 06:11:33 +0000
58+++ src/server/compositor/buffer_queue.cpp 2015-01-15 03:19:37 +0000
59@@ -100,6 +100,7 @@
60 frame_dropping_enabled{false},
61 the_properties{props},
62 force_new_compositor_buffer{false},
63+ callbacks_allowed{true},
64 gralloc{gralloc}
65 {
66 if (nbuffers < 1)
67@@ -434,6 +435,9 @@
68 [&]{ return !contains(buffer, pending_snapshots); });
69 }
70
71+ if (!callbacks_allowed) // We're shutting down
72+ return;
73+
74 buffers_owned_by_client.push_back(buffer);
75
76 lock.unlock();
77@@ -502,3 +506,10 @@
78 release(buffer, std::move(lock));
79 }
80 }
81+
82+void mc::BufferQueue::drop_client_requests()
83+{
84+ std::unique_lock<std::mutex> lock(guard);
85+ callbacks_allowed = false;
86+ pending_client_notifications.clear();
87+}
88
89=== modified file 'src/server/compositor/buffer_queue.h'
90--- src/server/compositor/buffer_queue.h 2014-09-30 06:11:33 +0000
91+++ src/server/compositor/buffer_queue.h 2015-01-15 03:19:37 +0000
92@@ -63,6 +63,7 @@
93 bool framedropping_allowed() const;
94 bool is_a_current_buffer_user(void const* user_id) const;
95 void drop_old_buffers() override;
96+ void drop_client_requests() override;
97
98 private:
99 void give_buffer_to_client(graphics::Buffer* buffer,
100@@ -89,6 +90,7 @@
101 bool frame_dropping_enabled;
102 graphics::BufferProperties the_properties;
103 bool force_new_compositor_buffer;
104+ bool callbacks_allowed;
105
106 std::condition_variable snapshot_released;
107 std::shared_ptr<graphics::GraphicBufferAllocator> gralloc;
108
109=== modified file 'src/server/compositor/buffer_stream_surfaces.cpp'
110--- src/server/compositor/buffer_stream_surfaces.cpp 2014-09-11 05:51:44 +0000
111+++ src/server/compositor/buffer_stream_surfaces.cpp 2015-01-15 03:19:37 +0000
112@@ -94,3 +94,8 @@
113 {
114 buffer_bundle->drop_old_buffers();
115 }
116+
117+void mc::BufferStreamSurfaces::drop_client_requests()
118+{
119+ buffer_bundle->drop_client_requests();
120+}
121
122=== modified file 'src/server/compositor/buffer_stream_surfaces.h'
123--- src/server/compositor/buffer_stream_surfaces.h 2014-09-11 05:51:44 +0000
124+++ src/server/compositor/buffer_stream_surfaces.h 2015-01-15 03:19:37 +0000
125@@ -53,6 +53,7 @@
126 void force_requests_to_complete() override;
127 int buffers_ready_for_compositor() const override;
128 void drop_old_buffers() override;
129+ void drop_client_requests() override;
130
131 protected:
132 BufferStreamSurfaces(const BufferStreamSurfaces&) = delete;
133
134=== modified file 'src/server/scene/basic_surface.cpp'
135--- src/server/scene/basic_surface.cpp 2014-09-26 08:16:25 +0000
136+++ src/server/scene/basic_surface.cpp 2015-01-15 03:19:37 +0000
137@@ -151,6 +151,9 @@
138 ms::BasicSurface::~BasicSurface() noexcept
139 {
140 report->surface_deleted(this, surface_name);
141+
142+ if (surface_buffer_stream) // some tests use null for surface_buffer_stream
143+ surface_buffer_stream->drop_client_requests();
144 }
145
146 std::shared_ptr<mc::BufferStream> ms::BasicSurface::buffer_stream() const
147
148=== modified file 'tests/include/mir_test_doubles/mock_buffer_bundle.h'
149--- tests/include/mir_test_doubles/mock_buffer_bundle.h 2014-09-11 05:51:44 +0000
150+++ tests/include/mir_test_doubles/mock_buffer_bundle.h 2015-01-15 03:19:37 +0000
151@@ -51,6 +51,7 @@
152 MOCK_METHOD0(drop_old_buffers, void());
153 int buffers_ready_for_compositor() const override { return 1; }
154 int buffers_free_for_client() const override { return 1; }
155+ void drop_client_requests() override {}
156 };
157
158 }
159
160=== modified file 'tests/include/mir_test_doubles/mock_buffer_stream.h'
161--- tests/include/mir_test_doubles/mock_buffer_stream.h 2014-09-11 05:51:44 +0000
162+++ tests/include/mir_test_doubles/mock_buffer_stream.h 2015-01-15 03:19:37 +0000
163@@ -58,6 +58,7 @@
164 MOCK_METHOD0(force_requests_to_complete, void());
165 MOCK_CONST_METHOD0(buffers_ready_for_compositor, int());
166 MOCK_METHOD0(drop_old_buffers, void());
167+ MOCK_METHOD0(drop_client_requests, void());
168 };
169 }
170 }
171
172=== modified file 'tests/include/mir_test_doubles/stub_buffer_stream.h'
173--- tests/include/mir_test_doubles/stub_buffer_stream.h 2014-09-11 05:51:44 +0000
174+++ tests/include/mir_test_doubles/stub_buffer_stream.h 2015-01-15 03:19:37 +0000
175@@ -82,6 +82,7 @@
176 int buffers_ready_for_compositor() const override { return 1; }
177
178 void drop_old_buffers() override {}
179+ void drop_client_requests() override {}
180
181 StubBuffer stub_client_buffer;
182 std::shared_ptr<graphics::Buffer> stub_compositor_buffer;
183
184=== modified file 'tests/integration-tests/CMakeLists.txt'
185--- tests/integration-tests/CMakeLists.txt 2014-10-03 20:09:41 +0000
186+++ tests/integration-tests/CMakeLists.txt 2015-01-15 03:19:37 +0000
187@@ -24,6 +24,7 @@
188 test_session_manager.cpp
189 test_session.cpp
190 session_management.cpp
191+ surface_composition.cpp
192 )
193
194 add_subdirectory(client/)
195
196=== added file 'tests/integration-tests/surface_composition.cpp'
197--- tests/integration-tests/surface_composition.cpp 1970-01-01 00:00:00 +0000
198+++ tests/integration-tests/surface_composition.cpp 2015-01-15 03:19:37 +0000
199@@ -0,0 +1,125 @@
200+/*
201+ * Copyright © 2014 Canonical Ltd.
202+ *
203+ * This program is free software: you can redistribute it and/or modify it
204+ * under the terms of the GNU General Public License version 3,
205+ * as published by the Free Software Foundation.
206+ *
207+ * This program is distributed in the hope that it will be useful,
208+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
209+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
210+ * GNU General Public License for more details.
211+ *
212+ * You should have received a copy of the GNU General Public License
213+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
214+ *
215+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
216+ */
217+
218+#include "src/server/scene/basic_surface.h"
219+#include "src/server/report/null_report_factory.h"
220+#include "src/server/compositor/buffer_stream_surfaces.h"
221+#include "src/server/compositor/buffer_queue.h"
222+
223+#include "mir_test_doubles/null_surface_configurator.h"
224+#include "mir_test_doubles/stub_buffer_allocator.h"
225+#include "mir_test_doubles/stub_frame_dropping_policy_factory.h"
226+#include "mir_test_doubles/stub_input_sender.h"
227+
228+#include <gmock/gmock.h>
229+#include <gtest/gtest.h>
230+
231+namespace geom = mir::geometry;
232+namespace mc = mir::compositor;
233+namespace mg = mir::graphics;
234+namespace mi = mir::input;
235+namespace mr = mir::report;
236+namespace ms = mir::scene;
237+namespace mtd = mir::test::doubles;
238+
239+using namespace testing;
240+
241+namespace
242+{
243+struct SurfaceComposition : Test
244+{
245+ auto create_surface() const
246+ -> std::shared_ptr<ms::Surface>
247+ {
248+ return std::make_shared<ms::BasicSurface>(
249+ std::string("SurfaceComposition"),
250+ geom::Rectangle{{},{}},
251+ false,
252+ create_buffer_stream(),
253+ create_input_channel(),
254+ create_input_sender(),
255+ create_surface_configurator(),
256+ create_cursor_image(),
257+ mr::null_scene_report());
258+
259+ }
260+
261+ int const number_of_buffers = 3;
262+
263+ auto create_buffer_stream() const
264+ ->std::shared_ptr<mc::BufferStream>
265+ {
266+ return std::make_shared<mc::BufferStreamSurfaces>(create_buffer_bundle());
267+ }
268+
269+ auto create_buffer_bundle() const
270+ -> std::shared_ptr<mc::BufferBundle>
271+ {
272+ return std::make_shared<mc::BufferQueue>(
273+ number_of_buffers,
274+ allocator,
275+ basic_properties,
276+ policy_factory);
277+ }
278+
279+ auto create_input_channel() const
280+ -> std::shared_ptr<mi::InputChannel> { return {}; }
281+
282+ auto create_cursor_image() const
283+ -> std::shared_ptr<mg::CursorImage> { return {}; }
284+
285+ auto create_surface_configurator() const
286+ -> std::shared_ptr<ms::SurfaceConfigurator>
287+ { return std::make_shared<mtd::NullSurfaceConfigurator>(); }
288+
289+ auto create_input_sender() const
290+ -> std::shared_ptr<mi::InputSender>
291+ { return std::make_shared<mtd::StubInputSender>(); }
292+
293+ std::shared_ptr<mg::GraphicBufferAllocator> const allocator
294+ {std::make_shared<mtd::StubBufferAllocator>()};
295+
296+ mg::BufferProperties const basic_properties
297+ { geom::Size{3, 4}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware };
298+
299+ mtd::StubFrameDroppingPolicyFactory policy_factory;
300+};
301+}
302+
303+// Presumptive cause of lp:1376324
304+TEST_F(SurfaceComposition, does_not_send_client_buffers_to_dead_surfaces)
305+{
306+ auto surface = create_surface();
307+
308+ mg::Buffer* old_buffer{nullptr};
309+
310+ auto const callback = [&] (mg::Buffer* new_buffer)
311+ {
312+ // If surface is dead then callback is not expected
313+ EXPECT_THAT(surface.get(), NotNull());
314+ old_buffer = new_buffer;
315+ };
316+
317+ // Exhaust the buffers to ensure we have a pending swap to complete
318+ for (auto i = 0; i != number_of_buffers; ++i)
319+ surface->swap_buffers(old_buffer, callback);
320+
321+ auto const renderable = surface->compositor_snapshot(this);
322+
323+ surface.reset();
324+}
325
326=== modified file 'tests/integration-tests/test_exchange_buffer.cpp'
327--- tests/integration-tests/test_exchange_buffer.cpp 2014-09-15 18:20:14 +0000
328+++ tests/integration-tests/test_exchange_buffer.cpp 2015-01-15 03:19:37 +0000
329@@ -78,6 +78,7 @@
330 void force_requests_to_complete() {};
331 int buffers_ready_for_compositor() const { return -5; }
332 void drop_old_buffers() {}
333+ void drop_client_requests() override {}
334
335 std::vector<std::shared_ptr<mg::Buffer>> client_buffers;
336 std::vector<mg::BufferID> const buffer_id_seq;
337
338=== modified file 'tests/unit-tests/compositor/test_buffer_queue.cpp'
339--- tests/unit-tests/compositor/test_buffer_queue.cpp 2014-09-30 06:11:33 +0000
340+++ tests/unit-tests/compositor/test_buffer_queue.cpp 2015-01-15 03:19:37 +0000
341@@ -695,6 +695,27 @@
342 }
343 }
344
345+TEST_F(BufferQueueTest, callbacks_cant_happen_after_shutdown)
346+{
347+ mc::BufferQueue q(1, allocator, basic_properties, policy_factory);
348+
349+ q.drop_client_requests();
350+ auto client = client_acquire_async(q);
351+ ASSERT_FALSE(client->has_acquired_buffer());
352+}
353+
354+TEST_F(BufferQueueTest, callbacks_cant_happen_after_shutdown_with_snapshots)
355+{
356+ mc::BufferQueue q(1, allocator, basic_properties, policy_factory);
357+
358+ auto snapshot = q.snapshot_acquire();
359+ q.drop_client_requests();
360+ q.snapshot_release(snapshot);
361+
362+ auto client = client_acquire_async(q);
363+ ASSERT_FALSE(client->has_acquired_buffer());
364+}
365+
366 TEST_F(BufferQueueTest, snapshot_acquire_never_blocks)
367 {
368 for (int nbuffers = 1; nbuffers <= max_nbuffers_to_test; ++nbuffers)

Subscribers

People subscribed via source and target branches

to all changes: