Mir

Merge lp:~vanvugt/mir/fix-racy-BufferMap-operator into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 4064
Proposed branch: lp:~vanvugt/mir/fix-racy-BufferMap-operator
Merge into: lp:mir
Diff against target: 230 lines (+28/-20)
13 files modified
include/server/mir/frontend/client_buffers.h (+1/-1)
src/server/compositor/buffer_map.cpp (+10/-1)
src/server/compositor/buffer_map.h (+2/-1)
src/server/compositor/stream.cpp (+2/-2)
src/server/scene/application_session.cpp (+1/-1)
tests/include/mir/test/doubles/stub_buffer_stream_factory.h (+1/-1)
tests/integration-tests/test_buffer_scheduling.cpp (+1/-1)
tests/integration-tests/test_submit_buffer.cpp (+1/-1)
tests/unit-tests/compositor/test_client_buffers.cpp (+4/-4)
tests/unit-tests/compositor/test_dropping_schedule.cpp (+1/-2)
tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp (+1/-2)
tests/unit-tests/compositor/test_stream.cpp (+2/-2)
tests/unit-tests/scene/test_surface_stack.cpp (+1/-1)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-racy-BufferMap-operator
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Alan Griffiths Approve
Review via email: mp+318751@code.launchpad.net

Commit message

Fix racy compositor::BufferMap::operator[] returning a reference from inside a lock.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4067
https://mir-jenkins.ubuntu.com/job/mir-ci/3095/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4144/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4231
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4221
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4221
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4221
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4171
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4171/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4171
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4171/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4171
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4171/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4171
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4171/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4171
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4171/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4171/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3095/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4068
https://mir-jenkins.ubuntu.com/job/mir-ci/3096/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4145
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4232
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4222
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4222
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4222
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4172/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4172/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4172/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4172/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4172/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4172
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4172/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3096/rebuild

review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Looks sensible

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/frontend/client_buffers.h'
--- include/server/mir/frontend/client_buffers.h 2017-01-30 08:13:20 +0000
+++ include/server/mir/frontend/client_buffers.h 2017-03-02 12:43:44 +0000
@@ -32,7 +32,7 @@
32public:32public:
33 virtual graphics::BufferID add_buffer(std::shared_ptr<graphics::Buffer> const& properties) = 0;33 virtual graphics::BufferID add_buffer(std::shared_ptr<graphics::Buffer> const& properties) = 0;
34 virtual void remove_buffer(graphics::BufferID id) = 0;34 virtual void remove_buffer(graphics::BufferID id) = 0;
35 virtual std::shared_ptr<graphics::Buffer>& operator[](graphics::BufferID) = 0;35 virtual std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const = 0;
36 virtual void send_buffer(graphics::BufferID id) = 0;36 virtual void send_buffer(graphics::BufferID id) = 0;
37 virtual void receive_buffer(graphics::BufferID id) = 0;37 virtual void receive_buffer(graphics::BufferID id) = 0;
3838
3939
=== modified file 'src/server/compositor/buffer_map.cpp'
--- src/server/compositor/buffer_map.cpp 2017-01-30 08:13:20 +0000
+++ src/server/compositor/buffer_map.cpp 2017-03-02 12:43:44 +0000
@@ -91,7 +91,7 @@
91 it->second.owner = Owner::server;91 it->second.owner = Owner::server;
92}92}
9393
94std::shared_ptr<mg::Buffer>& mc::BufferMap::operator[](mg::BufferID id)94std::shared_ptr<mg::Buffer> mc::BufferMap::get(mg::BufferID id) const
95{95{
96 std::unique_lock<decltype(mutex)> lk(mutex);96 std::unique_lock<decltype(mutex)> lk(mutex);
97 return checked_buffers_find(id, lk)->second.buffer;97 return checked_buffers_find(id, lk)->second.buffer;
@@ -105,3 +105,12 @@
105 BOOST_THROW_EXCEPTION(std::logic_error("cannot find buffer by id"));105 BOOST_THROW_EXCEPTION(std::logic_error("cannot find buffer by id"));
106 return it;106 return it;
107}107}
108
109mc::BufferMap::Map::const_iterator mc::BufferMap::checked_buffers_find(
110 mg::BufferID id, std::unique_lock<std::mutex> const&) const
111{
112 auto it = buffers.find(id);
113 if (it == buffers.end())
114 BOOST_THROW_EXCEPTION(std::logic_error("cannot find buffer by id"));
115 return it;
116}
108117
=== modified file 'src/server/compositor/buffer_map.h'
--- src/server/compositor/buffer_map.h 2017-01-30 08:13:20 +0000
+++ src/server/compositor/buffer_map.h 2017-03-02 12:43:44 +0000
@@ -39,7 +39,7 @@
39 void receive_buffer(graphics::BufferID id) override;39 void receive_buffer(graphics::BufferID id) override;
40 void send_buffer(graphics::BufferID id) override;40 void send_buffer(graphics::BufferID id) override;
4141
42 std::shared_ptr<graphics::Buffer>& operator[](graphics::BufferID) override;42 std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const override;
43 43
44private:44private:
45 std::mutex mutable mutex;45 std::mutex mutable mutex;
@@ -54,6 +54,7 @@
54 //used to keep strong reference54 //used to keep strong reference
55 Map buffers;55 Map buffers;
56 Map::iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&);56 Map::iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&);
57 Map::const_iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&) const;
5758
58 //would be better to schedule the async buffer callbacks in the ipc subsystem,59 //would be better to schedule the async buffer callbacks in the ipc subsystem,
59 //instead of driving from within the compositor threads (LP: #1395421)60 //instead of driving from within the compositor threads (LP: #1395421)
6061
=== modified file 'src/server/compositor/stream.cpp'
--- src/server/compositor/stream.cpp 2017-02-21 21:43:12 +0000
+++ src/server/compositor/stream.cpp 2017-03-02 12:43:44 +0000
@@ -97,7 +97,7 @@
97 std::lock_guard<decltype(mutex)> lk(mutex); 97 std::lock_guard<decltype(mutex)> lk(mutex);
98 first_frame_posted = true;98 first_frame_posted = true;
99 buffers->receive_buffer(buffer->id());99 buffers->receive_buffer(buffer->id());
100 schedule->schedule((*buffers)[buffer->id()]);100 schedule->schedule(buffers->get(buffer->id()));
101 if (!associated_buffers.empty() && (client_owned_buffer_count(lk) == 0))101 if (!associated_buffers.empty() && (client_owned_buffer_count(lk) == 0))
102 drop_policy->swap_now_blocking();102 drop_policy->swap_now_blocking();
103 }103 }
@@ -247,7 +247,7 @@
247 else247 else
248 {248 {
249 for (auto it : associated_buffers)249 for (auto it : associated_buffers)
250 if ((*buffers)[it]->pixel_format() != mir_pixel_format_argb_8888)250 if (buffers->get(it)->pixel_format() != mir_pixel_format_argb_8888)
251 return false;251 return false;
252 }252 }
253 return true;253 return true;
254254
=== modified file 'src/server/scene/application_session.cpp'
--- src/server/scene/application_session.cpp 2017-02-24 12:21:55 +0000
+++ src/server/scene/application_session.cpp 2017-03-02 12:43:44 +0000
@@ -476,7 +476,7 @@
476476
477std::shared_ptr<mg::Buffer> ms::ApplicationSession::get_buffer(mg::BufferID id)477std::shared_ptr<mg::Buffer> ms::ApplicationSession::get_buffer(mg::BufferID id)
478{478{
479 return (*buffers)[id];479 return buffers->get(id);
480}480}
481481
482void ms::ApplicationSession::send_error(mir::ClientVisibleError const& error)482void ms::ApplicationSession::send_error(mir::ClientVisibleError const& error)
483483
=== modified file 'tests/include/mir/test/doubles/stub_buffer_stream_factory.h'
--- tests/include/mir/test/doubles/stub_buffer_stream_factory.h 2017-01-18 02:29:37 +0000
+++ tests/include/mir/test/doubles/stub_buffer_stream_factory.h 2017-03-02 12:43:44 +0000
@@ -39,7 +39,7 @@
39 void remove_buffer(graphics::BufferID) override39 void remove_buffer(graphics::BufferID) override
40 {40 {
41 }41 }
42 std::shared_ptr<graphics::Buffer>& operator[](graphics::BufferID) override42 std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const override
43 {43 {
44 return buffer;44 return buffer;
45 }45 }
4646
=== modified file 'tests/integration-tests/test_buffer_scheduling.cpp'
--- tests/integration-tests/test_buffer_scheduling.cpp 2017-01-30 05:18:36 +0000
+++ tests/integration-tests/test_buffer_scheduling.cpp 2017-03-02 12:43:44 +0000
@@ -485,7 +485,7 @@
485 if (!submit_stream)485 if (!submit_stream)
486 return;486 return;
487 mg::BufferID id{static_cast<unsigned int>(buffer.buffer_id())};487 mg::BufferID id{static_cast<unsigned int>(buffer.buffer_id())};
488 submit_stream->submit_buffer((*map)[id]);488 submit_stream->submit_buffer(map->get(id));
489 });489 });
490 ipc->on_allocate(490 ipc->on_allocate(
491 [this](geom::Size sz)491 [this](geom::Size sz)
492492
=== modified file 'tests/integration-tests/test_submit_buffer.cpp'
--- tests/integration-tests/test_submit_buffer.cpp 2017-01-30 08:13:20 +0000
+++ tests/integration-tests/test_submit_buffer.cpp 2017-03-02 12:43:44 +0000
@@ -142,7 +142,7 @@
142 {142 {
143 } 143 }
144144
145 std::shared_ptr<mg::Buffer>& operator[](mg::BufferID) override145 std::shared_ptr<mg::Buffer> get(mg::BufferID) const override
146 {146 {
147 return b;147 return b;
148 }148 }
149149
=== modified file 'tests/unit-tests/compositor/test_client_buffers.cpp'
--- tests/unit-tests/compositor/test_client_buffers.cpp 2017-01-30 08:13:20 +0000
+++ tests/unit-tests/compositor/test_client_buffers.cpp 2017-03-02 12:43:44 +0000
@@ -49,7 +49,7 @@
49TEST_F(ClientBuffers, access_of_nonexistent_buffer_throws)49TEST_F(ClientBuffers, access_of_nonexistent_buffer_throws)
50{50{
51 EXPECT_THROW({51 EXPECT_THROW({
52 auto buffer = map[stub_buffer.id()];52 auto buffer = map.get(stub_buffer.id());
53 }, std::logic_error);53 }, std::logic_error);
54}54}
5555
@@ -63,13 +63,13 @@
63TEST_F(ClientBuffers, can_access_once_added)63TEST_F(ClientBuffers, can_access_once_added)
64{64{
65 auto id = map.add_buffer(mt::fake_shared(stub_buffer));65 auto id = map.add_buffer(mt::fake_shared(stub_buffer));
66 EXPECT_THAT(map[id].get(), Eq(&stub_buffer));66 EXPECT_THAT(map.get(id).get(), Eq(&stub_buffer));
67}67}
6868
69TEST_F(ClientBuffers, sends_update_msg_to_send_buffer)69TEST_F(ClientBuffers, sends_update_msg_to_send_buffer)
70{70{
71 auto id = map.add_buffer(mt::fake_shared(stub_buffer));71 auto id = map.add_buffer(mt::fake_shared(stub_buffer));
72 auto buffer = map[id];72 auto buffer = map.get(id);
73 EXPECT_CALL(*mock_sink, update_buffer(Ref(*buffer)));73 EXPECT_CALL(*mock_sink, update_buffer(Ref(*buffer)));
74 map.send_buffer(id);74 map.send_buffer(id);
75}75}
@@ -77,7 +77,7 @@
77TEST_F(ClientBuffers, sends_no_update_msg_if_buffer_is_not_around)77TEST_F(ClientBuffers, sends_no_update_msg_if_buffer_is_not_around)
78{78{
79 auto id = map.add_buffer(mt::fake_shared(stub_buffer));79 auto id = map.add_buffer(mt::fake_shared(stub_buffer));
80 auto buffer = map[id];80 auto buffer = map.get(id);
8181
82 EXPECT_CALL(*mock_sink, remove_buffer(Ref(*buffer)));82 EXPECT_CALL(*mock_sink, remove_buffer(Ref(*buffer)));
83 map.remove_buffer(id);83 map.remove_buffer(id);
8484
=== modified file 'tests/unit-tests/compositor/test_dropping_schedule.cpp'
--- tests/unit-tests/compositor/test_dropping_schedule.cpp 2017-01-18 02:29:37 +0000
+++ tests/unit-tests/compositor/test_dropping_schedule.cpp 2017-03-02 12:43:44 +0000
@@ -38,9 +38,8 @@
38 MOCK_METHOD1(remove_buffer, void(mg::BufferID id));38 MOCK_METHOD1(remove_buffer, void(mg::BufferID id));
39 MOCK_METHOD1(send_buffer, void(mg::BufferID id));39 MOCK_METHOD1(send_buffer, void(mg::BufferID id));
40 MOCK_METHOD1(receive_buffer, void(mg::BufferID id));40 MOCK_METHOD1(receive_buffer, void(mg::BufferID id));
41 MOCK_METHOD1(at, std::shared_ptr<mg::Buffer>&(mg::BufferID));
42 MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());41 MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());
43 std::shared_ptr<mg::Buffer>& operator[](mg::BufferID id) { return at(id); }42 MOCK_CONST_METHOD1(get, std::shared_ptr<mg::Buffer>(mg::BufferID));
44};43};
4544
46struct DroppingSchedule : Test45struct DroppingSchedule : Test
4746
=== modified file 'tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp'
--- tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp 2017-02-15 19:14:27 +0000
+++ tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp 2017-03-02 12:43:44 +0000
@@ -39,9 +39,8 @@
39 MOCK_METHOD1(remove_buffer, void(mg::BufferID id));39 MOCK_METHOD1(remove_buffer, void(mg::BufferID id));
40 MOCK_METHOD1(receive_buffer, void(mg::BufferID id));40 MOCK_METHOD1(receive_buffer, void(mg::BufferID id));
41 MOCK_METHOD1(send_buffer, void(mg::BufferID id));41 MOCK_METHOD1(send_buffer, void(mg::BufferID id));
42 MOCK_METHOD1(at, std::shared_ptr<mg::Buffer>&(mg::BufferID));
43 MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());42 MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());
44 std::shared_ptr<mg::Buffer>& operator[](mg::BufferID id) { return at(id); }43 MOCK_CONST_METHOD1(get, std::shared_ptr<mg::Buffer>(mg::BufferID));
45};44};
4645
47struct FixedSchedule : mc::Schedule46struct FixedSchedule : mc::Schedule
4847
=== modified file 'tests/unit-tests/compositor/test_stream.cpp'
--- tests/unit-tests/compositor/test_stream.cpp 2017-01-18 02:29:37 +0000
+++ tests/unit-tests/compositor/test_stream.cpp 2017-03-02 12:43:44 +0000
@@ -64,9 +64,9 @@
64 }64 }
65 void send_buffer(mg::BufferID id)65 void send_buffer(mg::BufferID id)
66 {66 {
67 sink.send_buffer(mf::BufferStreamId{33}, *operator[](id), mg::BufferIpcMsgType::update_msg);67 sink.send_buffer(mf::BufferStreamId{33}, *get(id), mg::BufferIpcMsgType::update_msg);
68 }68 }
69 std::shared_ptr<mg::Buffer>& operator[](mg::BufferID id)69 std::shared_ptr<mg::Buffer> get(mg::BufferID id) const
70 {70 {
71 auto it = std::find_if(buffers.begin(), buffers.end(),71 auto it = std::find_if(buffers.begin(), buffers.end(),
72 [id](std::shared_ptr<mg::Buffer> const& b)72 [id](std::shared_ptr<mg::Buffer> const& b)
7373
=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
--- tests/unit-tests/scene/test_surface_stack.cpp 2017-02-15 14:45:41 +0000
+++ tests/unit-tests/scene/test_surface_stack.cpp 2017-03-02 12:43:44 +0000
@@ -292,7 +292,7 @@
292292
293 struct StubBuffers : mtd::StubClientBuffers293 struct StubBuffers : mtd::StubClientBuffers
294 {294 {
295 std::shared_ptr<mg::Buffer>& operator[](mg::BufferID) override295 std::shared_ptr<mg::Buffer> get(mg::BufferID) const override
296 {296 {
297 return buffer;297 return buffer;
298 }298 }

Subscribers

People subscribed via source and target branches