Mir

Merge lp:~vanvugt/mir/reply-buffer-allocation-failures into lp:mir

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Daniel van Vugt
Proposed branch: lp:~vanvugt/mir/reply-buffer-allocation-failures
Merge into: lp:mir
Diff against target: 135 lines (+75/-17)
2 files modified
src/server/frontend/session_mediator.cpp (+42/-16)
tests/unit-tests/frontend/test_session_mediator.cpp (+33/-1)
To merge this branch: bzr merge lp:~vanvugt/mir/reply-buffer-allocation-failures
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Information
Alan Griffiths Abstain
Mir CI Bot continuous-integration Approve
Review via email: mp+310753@code.launchpad.net

Commit message

If buffer allocation fails, remember to tell the client by setting
the error fields in the reply.

Also log a warning to the server log, since buffer allocation failure
means either the server is out of resources or the graphics driver
is not working yet (VirtualBox). Both of those are more problems with
the server than with the client.

For now, clients will still (since NBS was introduced anyway) ignore
such error reports and just hang forever waiting for their buffers (in
swap) that didn't get created. So more work is required still to make
clients recognise the error fields in buffer replies.

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

PASSED: Continuous integration, rev:3823
https://mir-jenkins.ubuntu.com/job/mir-ci/2158/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2796
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2861
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2853
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2853
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2853
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2825/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/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2825/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2825/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/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2825/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/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2825/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/2825
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2825/artifact/output/*zip*/output.zip

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

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

It seems questionable to insert error handling here that (almost) duplicates that a couple of stack frames above (in invoke<>()). But I understand your desire to do "something".

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

If you mean more like this location, that might be doable:

https://code.launchpad.net/~vanvugt/mir/log-unhandled-exceptions/+merge/310398

But I'm running scared from that branch right now. Too much pointless argument over there.

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

Actually I did have two good reasons for this branch based on the contention that previous branch caused:

(1) Buffer allocation failure is always a server error worth mentioning. Logging warnings about other exceptions might be overkill and inappropriate (?). Although in that previous branch I was gambling on that being untrue and we could just find out the truth eventually by reading our logs.

(2) Buffer allocation failures from the driver may contain very detailed and confusing error strings so should all be prefixed with something meaningful "Buffer allocation failed". Admittedly we could just do that by ensuring all graphics drivers provide nice strings.

Needs Information: I shall check if it's possible to make a generalised hybrid of that other branch and this one. It would be nice to reuse existing catches instead of adding new ones.

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

Rejected. Replies with the error field set are already being sent from a different catch. Just I never realised because there is no logging in the client or server. The only definite problem is that libmirclient ignores error responses and waits for non-error responses forever.

Unmerged revisions

3823. By Daniel van Vugt

Enable the fix and the test now passes

3822. By Daniel van Vugt

Disable the fix and introduce a regression test

3821. By Daniel van Vugt

Cherry pick the bit that works from today's branch (just the server side)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/frontend/session_mediator.cpp'
2--- src/server/frontend/session_mediator.cpp 2016-11-11 07:56:09 +0000
3+++ src/server/frontend/session_mediator.cpp 2016-11-14 10:19:53 +0000
4@@ -53,6 +53,8 @@
5 #include "mir/fd.h"
6 #include "mir/cookie/authority.h"
7 #include "mir/module_properties.h"
8+#include "mir/client_visible_error.h"
9+#include "mir/log.h"
10
11 #include "mir/geometry/rectangles.h"
12 #include "protobuf_buffer_packer.h"
13@@ -389,29 +391,53 @@
14
15 void mf::SessionMediator::allocate_buffers(
16 mir::protobuf::BufferAllocation const* request,
17- mir::protobuf::Void*,
18+ mir::protobuf::Void* result,
19 google::protobuf::Closure* done)
20 {
21- auto session = weak_session.lock();
22- if (!session)
23- BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
24-
25- report->session_allocate_buffers_called(session->name());
26- for (auto i = 0; i < request->buffer_requests().size(); i++)
27+ try
28 {
29- auto const& req = request->buffer_requests(i);
30- mg::BufferProperties properties(
31- geom::Size{req.width(), req.height()},
32- static_cast<MirPixelFormat>(req.pixel_format()),
33- static_cast<mg::BufferUsage>(req.buffer_usage()));
34+ auto session = weak_session.lock();
35+ if (!session)
36+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
37
38- auto id = session->create_buffer(properties);
39- if (request->has_id())
40+ report->session_allocate_buffers_called(session->name());
41+ for (auto i = 0; i < request->buffer_requests().size(); i++)
42 {
43- auto stream = session->get_buffer_stream(mf::BufferStreamId(request->id().value()));
44- stream->associate_buffer(id);
45+ auto const& req = request->buffer_requests(i);
46+ mg::BufferProperties properties(
47+ geom::Size{req.width(), req.height()},
48+ static_cast<MirPixelFormat>(req.pixel_format()),
49+ static_cast<mg::BufferUsage>(req.buffer_usage()));
50+
51+ auto id = session->create_buffer(properties);
52+ if (request->has_id())
53+ {
54+ auto stream = session->get_buffer_stream(mf::BufferStreamId(request->id().value()));
55+ stream->associate_buffer(id);
56+ }
57 }
58 }
59+ // This is a misnomer: "ClientVisibleError" is not the only type of
60+ // exception that clients should be notified of...
61+ catch (mir::ClientVisibleError const& e)
62+ {
63+ auto const msg =
64+ std::string{"Buffer allocation failed: "} + e.what();
65+ result->set_error(msg);
66+ auto se = result->mutable_structured_error();
67+ se->set_domain(e.domain());
68+ se->set_code(e.code());
69+ mir::log_warning(msg);
70+ }
71+ // ... notify clients of traditional errors too. Which catch is used
72+ // just depends on the type of exception the graphics driver likes to use.
73+ catch (std::exception const& e)
74+ {
75+ auto const msg =
76+ std::string{"Buffer allocation failed: "} + e.what();
77+ result->set_error(msg);
78+ mir::log_warning(msg);
79+ }
80 done->Run();
81 }
82
83
84=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
85--- tests/unit-tests/frontend/test_session_mediator.cpp 2016-11-09 02:30:14 +0000
86+++ tests/unit-tests/frontend/test_session_mediator.cpp 2016-11-14 10:19:53 +0000
87@@ -200,8 +200,12 @@
88 }
89
90
91- mg::BufferID create_buffer(mg::BufferProperties const&) override
92+ mg::BufferID create_buffer(mg::BufferProperties const& prop) override
93 {
94+ if (!prop.size.width.as_int() || !prop.size.height.as_int())
95+ {
96+ throw std::runtime_error("Driver refused to allocate buffer");
97+ }
98 buffer_count++;
99 return mg::BufferID{3};
100 }
101@@ -701,6 +705,34 @@
102 EXPECT_THAT(stubbed_session->num_alloc_requests(), Eq(num_requests));
103 }
104
105+TEST_F(SessionMediator, buffer_allocation_failure_returns_error)
106+{
107+ mp::BufferAllocation request;
108+ mp::BufferStreamId id;
109+ id.set_value(0);
110+ *request.mutable_id() = id;
111+ mg::BufferProperties properties(geom::Size{0, 0},
112+ mir_pixel_format_abgr_8888,
113+ mg::BufferUsage::hardware);
114+ for (int i = 0; i < 3; ++i)
115+ {
116+ auto buffer_request = request.add_buffer_requests();
117+ buffer_request->set_width(properties.size.width.as_int());
118+ buffer_request->set_height(properties.size.height.as_int());
119+ buffer_request->set_pixel_format(properties.format);
120+ buffer_request->set_buffer_usage((int)properties.usage);
121+ }
122+
123+ mediator.connect(&connect_parameters, &connection, null_callback.get());
124+ mediator.create_surface(&surface_parameters, &surface_response,
125+ null_callback.get());
126+
127+ mir::protobuf::Void result;
128+ mediator.allocate_buffers(&request, &result, null_callback.get());
129+ ASSERT_TRUE(result.has_error());
130+ EXPECT_FALSE(result.error().empty());
131+}
132+
133 TEST_F(SessionMediator, removes_buffer_from_the_session)
134 {
135 using namespace testing;

Subscribers

People subscribed via source and target branches