Mir

Merge lp:~afrantzis/mir/fix-1306464 into lp:mir

Proposed by Alexandros Frantzis
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1550
Proposed branch: lp:~afrantzis/mir/fix-1306464
Merge into: lp:mir
Diff against target: 153 lines (+85/-11)
3 files modified
include/test/mir_test/wait_condition.h (+11/-4)
src/server/compositor/switching_bundle.cpp (+17/-7)
tests/unit-tests/compositor/test_switching_bundle.cpp (+57/-0)
To merge this branch: bzr merge lp:~afrantzis/mir/fix-1306464
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
Alberto Aguirre (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+215387@code.launchpad.net

Commit message

compositor: Don't block in SwitchingBundle::client_acquire() when a framedropping bundle has no free or ready buffers

Description of the change

compositor: Don't block in SwitchingBundle::client_acquire() when a framedropping bundle has no free or ready buffers

Fixes https://bugs.launchpad.net/mir/+bug/1306464 which cause intermittent CI failures.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

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

Seems OK

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/test/mir_test/wait_condition.h'
--- include/test/mir_test/wait_condition.h 2013-04-24 05:22:20 +0000
+++ include/test/mir_test/wait_condition.h 2014-04-11 10:56:45 +0000
@@ -31,24 +31,31 @@
31{31{
32struct WaitCondition32struct WaitCondition
33{33{
34 WaitCondition() : woken(false) {}34 WaitCondition() : woken_(false) {}
3535
36 void wait_for_at_most_seconds(int seconds)36 void wait_for_at_most_seconds(int seconds)
37 {37 {
38 std::unique_lock<std::mutex> ul(guard);38 std::unique_lock<std::mutex> ul(guard);
39 if (!woken) condition.wait_for(ul, std::chrono::seconds(seconds));39 condition.wait_for(ul, std::chrono::seconds(seconds),
40 [this] { return woken_; });
40 }41 }
4142
42 void wake_up_everyone()43 void wake_up_everyone()
43 {44 {
44 std::unique_lock<std::mutex> ul(guard);45 std::unique_lock<std::mutex> ul(guard);
45 woken = true;46 woken_ = true;
46 condition.notify_all();47 condition.notify_all();
47 }48 }
4849
50 bool woken()
51 {
52 std::unique_lock<std::mutex> ul(guard);
53 return woken_;
54 }
55
49 std::mutex guard;56 std::mutex guard;
50 std::condition_variable condition;57 std::condition_variable condition;
51 bool woken;58 bool woken_;
52};59};
5360
54ACTION_P(ReturnFalseAndWakeUp, wait_condition)61ACTION_P(ReturnFalseAndWakeUp, wait_condition)
5562
=== modified file 'src/server/compositor/switching_bundle.cpp'
--- src/server/compositor/switching_bundle.cpp 2014-03-26 05:48:59 +0000
+++ src/server/compositor/switching_bundle.cpp 2014-04-11 10:56:45 +0000
@@ -212,13 +212,12 @@
212212
213 if ((framedropping || force_drop) && nbuffers > 1)213 if ((framedropping || force_drop) && nbuffers > 1)
214 {214 {
215 if (nfree() <= 0)215 /*
216 {216 * If we don't have a free buffer to return or we cannot free a ready buffer
217 while (nready == 0)217 * by dropping it, we would block in complete_client_acquire, so just return.
218 cond.wait(lock);218 */
219219 if (nfree() <= 0 && nready == 0)
220 drop_frames(1);220 return;
221 }
222 }221 }
223 else222 else
224 {223 {
@@ -233,6 +232,17 @@
233{232{
234 auto complete = std::move(client_acquire_todo);233 auto complete = std::move(client_acquire_todo);
235234
235 if ((framedropping || force_drop) && nbuffers > 1)
236 {
237 if (nfree() <= 0)
238 {
239 while (nready == 0)
240 cond.wait(lock);
241
242 drop_frames(1);
243 }
244 }
245
236 if (force_drop > 0)246 if (force_drop > 0)
237 force_drop--;247 force_drop--;
238248
239249
=== modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp'
--- tests/unit-tests/compositor/test_switching_bundle.cpp 2014-03-26 05:48:59 +0000
+++ tests/unit-tests/compositor/test_switching_bundle.cpp 2014-04-11 10:56:45 +0000
@@ -19,6 +19,7 @@
19#include "src/server/compositor/switching_bundle.h"19#include "src/server/compositor/switching_bundle.h"
20#include "mir_test_doubles/stub_buffer_allocator.h"20#include "mir_test_doubles/stub_buffer_allocator.h"
21#include "mir_test_doubles/stub_buffer.h"21#include "mir_test_doubles/stub_buffer.h"
22#include "mir_test/wait_condition.h"
2223
23#include <gtest/gtest.h>24#include <gtest/gtest.h>
2425
@@ -944,3 +945,59 @@
944 }945 }
945 }946 }
946}947}
948
949TEST_F(SwitchingBundleTest, framedropping_client_acquire_does_not_block_when_no_available_buffers)
950{
951 /* Regression test for LP: #1306464 */
952 using namespace testing;
953
954 int const nbuffers{3};
955 mc::SwitchingBundle bundle{nbuffers, allocator, basic_properties};
956
957 bundle.allow_framedropping(true);
958
959 mg::Buffer* buffer{nullptr};
960
961 for (int i = 0; i < nbuffers; ++i)
962 {
963 bundle.client_acquire([&] (mg::Buffer* b) { buffer = b; });
964 bundle.client_release(buffer);
965 }
966
967 /*
968 * We need nbuffers - 1 compositors to acquire all the buffers,
969 * each compositor acquiring buffers twice (see below)
970 */
971 std::vector<int> compositors(nbuffers - 1);
972 std::vector<std::shared_ptr<mg::Buffer>> buffers;
973
974 for (auto const& id : compositors)
975 {
976 buffers.push_back(bundle.compositor_acquire(&id));
977 buffers.push_back(bundle.compositor_acquire(&id));
978 }
979
980 /* At this point the bundle has 0 free buffers and 0 ready buffers */
981
982 mir::test::WaitCondition client_acquire_complete;
983
984 /*
985 * Although we neither have a free buffer, nor can we free a buffer by dropping it,
986 * this shouldn't block. BufferBundle::client_acquire() should *never* block.
987 */
988 bundle.client_acquire(
989 [&] (mg::Buffer*)
990 {
991 client_acquire_complete.wake_up_everyone();
992 });
993
994 /* Release compositor buffers so that the client can get one */
995 for (auto const& buffer : buffers)
996 {
997 bundle.compositor_release(buffer);
998 }
999
1000 client_acquire_complete.wait_for_at_most_seconds(5);
1001
1002 EXPECT_TRUE(client_acquire_complete.woken());
1003}

Subscribers

People subscribed via source and target branches