Mir

Merge lp:~robertcarr/mir/weak-session-for-session-mediator into lp:~mir-team/mir/trunk

Proposed by Robert Carr
Status: Merged
Approved by: Thomas Voß
Approved revision: no longer in the source branch.
Merged at revision: 1012
Proposed branch: lp:~robertcarr/mir/weak-session-for-session-mediator
Merge into: lp:~mir-team/mir/trunk
Diff against target: 222 lines (+60/-41)
5 files modified
include/server/mir/frontend/session_mediator.h (+1/-1)
include/test/mir_test_doubles/stub_shell.h (+6/-2)
src/server/frontend/session_mediator.cpp (+50/-38)
src/server/frontend/session_mediator_android.cpp (+2/-0)
src/server/frontend/session_mediator_gbm.cpp (+1/-0)
To merge this branch: bzr merge lp:~robertcarr/mir/weak-session-for-session-mediator
Reviewer Review Type Date Requested Status
Thomas Voß (community) Approve
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+181924@code.launchpad.net

Commit message

SessionMediator must hold only a weak reference to the session.

Description of the change

This is a stab at fixing the stress test, as discussed here: https://code.launchpad.net/~robertcarr/mir/session-transactions/+merge/175669 there are several ways open_session/close_session can throw (the get_surface + hold shared_ptr to msh::Surface 'race') leaving the session mediator in an invalid state, causing a fatal exception when it tries to say repeatedly close the session (from ~SessionMediator).

The SessionMediator now holds a weak reference to the session, with only the session container holding the strong reference. I think this is in general just a more consistent application of shared_ptrs, however it also fixes the double call to close_session which is throwing from ~SessionMediator.

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote :

So far I've been able to run the stress test for 30 minutes.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

So excited about the stress tests I forgot to run the unit tests ;)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Linked the bug which I assume is the one you're trying to fix...

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

Tested. The bug is half solved, so long as you don't use the mouse much.

Fixed:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::logic_error> >'
  what(): Invalid Session

Still reproduceable with mir_stress and some input on other clients:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::logic_error> >'
  what(): Requesting handle for an unregistered channel

Perhaps we need to take this as a half fix? Or divide the bug itself in two?

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

This is a rather important fix, in theory. And it works for me... We can log a new bug for the remaining input-related crash.

I'm also ignoring the minor indentation and whitespace mistakes.

review: Approve
Revision history for this message
Thomas Voß (thomas-voss) wrote :

LGTM. As Daniel, I'm ignoring the whitespace and indentation noise for now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/frontend/session_mediator.h'
2--- include/server/mir/frontend/session_mediator.h 2013-08-23 15:27:41 +0000
3+++ include/server/mir/frontend/session_mediator.h 2013-08-23 22:22:27 +0000
4@@ -123,7 +123,7 @@
5 std::shared_ptr<graphics::Buffer> client_buffer_resource;
6
7 std::mutex session_mutex;
8- std::shared_ptr<Session> session;
9+ std::weak_ptr<Session> weak_session;
10 };
11
12 }
13
14=== modified file 'include/test/mir_test_doubles/stub_shell.h'
15--- include/test/mir_test_doubles/stub_shell.h 2013-08-13 22:13:41 +0000
16+++ include/test/mir_test_doubles/stub_shell.h 2013-08-23 22:22:27 +0000
17@@ -29,11 +29,14 @@
18 namespace doubles
19 {
20
21-class StubShell : public frontend::Shell
22+struct StubShell : public frontend::Shell
23 {
24+ StubShell() : stub_session(std::make_shared<StubSession>())
25+ {
26+ }
27 std::shared_ptr<frontend::Session> open_session(std::string const& /* name */, std::shared_ptr<frontend::EventSink> const& /* sink */) override
28 {
29- return std::make_shared<StubSession>();
30+ return stub_session;
31 }
32 void close_session(std::shared_ptr<frontend::Session> const& /* session */) override
33 {
34@@ -46,6 +49,7 @@
35 void handle_surface_created(std::shared_ptr<frontend::Session> const& /* session */) override
36 {
37 }
38+ std::shared_ptr<StubSession> const stub_session;
39 };
40
41 }
42
43=== modified file 'src/server/frontend/session_mediator.cpp'
44--- src/server/frontend/session_mediator.cpp 2013-08-23 15:27:41 +0000
45+++ src/server/frontend/session_mediator.cpp 2013-08-23 22:22:27 +0000
46@@ -73,6 +73,7 @@
47
48 mf::SessionMediator::~SessionMediator() noexcept
49 {
50+ auto session = weak_session.lock();
51 if (session)
52 {
53 report->session_error(session->name(), __PRETTY_FUNCTION__, "connection dropped without disconnect");
54@@ -90,9 +91,9 @@
55
56 {
57 std::unique_lock<std::mutex> lock(session_mutex);
58- session = shell->open_session(request->application_name(), event_sink);
59+ weak_session = shell->open_session(request->application_name(), event_sink);
60 }
61-
62+
63 auto ipc_package = graphics_platform->get_ipc_package();
64 auto platform = response->mutable_platform();
65
66@@ -117,42 +118,40 @@
67 mir::protobuf::Surface* response,
68 google::protobuf::Closure* done)
69 {
70+ std::unique_lock<std::mutex> lock(session_mutex);
71+
72+ auto session = weak_session.lock();
73+
74+ if (session.get() == nullptr)
75+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
76+
77+ report->session_create_surface_called(session->name());
78+
79+ auto const id = session->create_surface(msh::SurfaceCreationParameters()
80+ .of_name(request->surface_name())
81+ .of_size(request->width(), request->height())
82+ .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
83+ .of_pixel_format(static_cast<geometry::PixelFormat>(request->pixel_format()))
84+ .with_output_id(graphics::DisplayConfigurationOutputId(request->output_id())));
85 {
86- std::unique_lock<std::mutex> lock(session_mutex);
87-
88- if (session.get() == nullptr)
89- BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
90-
91- report->session_create_surface_called(session->name());
92-
93- auto const id = session->create_surface(
94- msh::SurfaceCreationParameters()
95- .of_name(request->surface_name())
96- .of_size(request->width(), request->height())
97- .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
98- .of_pixel_format(static_cast<geometry::PixelFormat>(request->pixel_format()))
99- .with_output_id(graphics::DisplayConfigurationOutputId(request->output_id()))
100- );
101- {
102- auto surface = session->get_surface(id);
103- response->mutable_id()->set_value(id.as_value());
104- response->set_width(surface->size().width.as_uint32_t());
105- response->set_height(surface->size().height.as_uint32_t());
106- response->set_pixel_format((int)surface->pixel_format());
107- response->set_buffer_usage(request->buffer_usage());
108- if (surface->supports_input())
109- response->add_fd(surface->client_input_fd());
110- client_buffer_resource = surface->advance_client_buffer();
111- auto const& id = client_buffer_resource->id();
112- auto buffer = response->mutable_buffer();
113- buffer->set_buffer_id(id.as_uint32_t());
114- if (!client_tracker->client_has(id))
115- {
116- auto packer = std::make_shared<mfd::ProtobufBufferPacker>(buffer);
117- graphics_platform->fill_ipc_package(packer, client_buffer_resource);
118- }
119- client_tracker->add(id);
120- }
121+ auto surface = session->get_surface(id);
122+ response->mutable_id()->set_value(id.as_value());
123+ response->set_width(surface->size().width.as_uint32_t());
124+ response->set_height(surface->size().height.as_uint32_t());
125+ response->set_pixel_format((int)surface->pixel_format());
126+ response->set_buffer_usage(request->buffer_usage());
127+ if (surface->supports_input())
128+ response->add_fd(surface->client_input_fd());
129+ client_buffer_resource = surface->advance_client_buffer();
130+ auto const& id = client_buffer_resource->id();
131+ auto buffer = response->mutable_buffer();
132+ buffer->set_buffer_id(id.as_uint32_t());
133+ if (!client_tracker->client_has(id))
134+ {
135+ auto packer = std::make_shared<mfd::ProtobufBufferPacker>(buffer);
136+ graphics_platform->fill_ipc_package(packer, client_buffer_resource);
137+ }
138+ client_tracker->add(id);
139 }
140
141 // TODO: NOTE: We use the ordering here to ensure the shell acts on the surface after the surface ID is sent over the wire.
142@@ -171,6 +170,8 @@
143 {
144 {
145 std::unique_lock<std::mutex> lock(session_mutex);
146+
147+ auto session = weak_session.lock();
148
149 if (session.get() == nullptr)
150 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
151@@ -204,6 +205,8 @@
152 {
153 std::unique_lock<std::mutex> lock(session_mutex);
154
155+ auto session = weak_session.lock();
156+
157 if (session.get() == nullptr)
158 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
159
160@@ -227,13 +230,15 @@
161 {
162 std::unique_lock<std::mutex> lock(session_mutex);
163
164+ auto session = weak_session.lock();
165+
166 if (session.get() == nullptr)
167 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
168
169 report->session_disconnect_called(session->name());
170
171 shell->close_session(session);
172- session.reset();
173+ weak_session.reset();
174 }
175
176 done->Run();
177@@ -254,6 +259,8 @@
178 {
179 std::unique_lock<std::mutex> lock(session_mutex);
180
181+ auto session = weak_session.lock();
182+
183 if (session.get() == nullptr)
184 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
185
186@@ -277,6 +284,11 @@
187 {
188 {
189 std::unique_lock<std::mutex> lock(session_mutex);
190+ auto session = weak_session.lock();
191+
192+ if (session.get() == nullptr)
193+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
194+
195 auto config = display_changer->active_configuration();
196 for (auto i=0; i < request->display_output_size(); i++)
197 {
198
199=== modified file 'src/server/frontend/session_mediator_android.cpp'
200--- src/server/frontend/session_mediator_android.cpp 2013-07-05 16:40:27 +0000
201+++ src/server/frontend/session_mediator_android.cpp 2013-08-23 22:22:27 +0000
202@@ -31,6 +31,8 @@
203 {
204 {
205 std::unique_lock<std::mutex> lock(session_mutex);
206+
207+ auto session = weak_session.lock();
208
209 if (session.get() == nullptr)
210 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
211
212=== modified file 'src/server/frontend/session_mediator_gbm.cpp'
213--- src/server/frontend/session_mediator_gbm.cpp 2013-07-05 16:40:27 +0000
214+++ src/server/frontend/session_mediator_gbm.cpp 2013-08-23 22:22:27 +0000
215@@ -38,6 +38,7 @@
216 {
217 {
218 std::unique_lock<std::mutex> lock(session_mutex);
219+ auto session = weak_session.lock();
220
221 if (session.get() == nullptr)
222 BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));

Subscribers

People subscribed via source and target branches