Mir

Merge lp:~alan-griffiths/mir/cleanup-some-locking into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: kevin gunn
Approved revision: no longer in the source branch.
Merged at revision: 1316
Proposed branch: lp:~alan-griffiths/mir/cleanup-some-locking
Merge into: lp:mir
Diff against target: 725 lines (+103/-112)
10 files modified
src/client/mir_client_library.cpp (+1/-2)
src/client/mir_connection.cpp (+46/-46)
src/client/mir_connection.h (+3/-3)
src/client/mir_surface.cpp (+28/-33)
src/client/mir_surface.h (+3/-3)
src/client/rpc/mir_basic_rpc_channel.cpp (+16/-17)
src/client/rpc/mir_basic_rpc_channel.h (+1/-2)
src/client/rpc/mir_socket_rpc_channel.cpp (+3/-4)
src/client/rpc/mir_socket_rpc_channel.h (+1/-1)
tests/acceptance-tests/test_client_focus_notification.cpp (+1/-1)
To merge this branch: bzr merge lp:~alan-griffiths/mir/cleanup-some-locking
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Approve
Review via email: mp+199828@code.launchpad.net

Commit message

client: rework dubious locking design in client rpc
(LP: #1243576) (LP: #1243584) (LP: #1243578) (LP: #1243575)

Description of the change

client: rework dubious locking design in client rpc

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Verified bug 1243584 fixed.
Bug 1243576 remains... unlinking it.

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

To test and verify the bugs;
sudo valgrind --tool=helgrind --log-file=helgrind.log bin/mir_demo_client_egltriangle

The news is pretty good already as branch halves the size of the log.

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

(1) Bug 1243576 is still happening. Please fix it or unlink.

(2) Adding error_message_mutex seems to not achieve anything. Because the string returned by MirConnection::get_error_message() remains unprotected.

(3) std::mutex mutex; // Protects all members of *this that don't have their own
Is there a logical or performance reason why the class has multiple mutexes? If neither, then it would be easier to follow using just one.

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

(1)-(3) Nice. All fixed, I think. As possibly more (linked 4 bugs now).

(4) surface_map is no longer protected by a mutex in MirConnection. But now I see it has its own built-in. That might be worth a comment where it's called by MirConnection.

(5) This is getting very complex and hard to review now. Not least because the diff doesn't show what's protected by each lock_guard. I suggest aiming to only fix one bug at a time in future :)

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

I was able to reproduce Jenkins' failure of ServerDisconnect.client_detects_server_shutdown on mako. But only once and not repeatably, so can't prove it's due to this branch.

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

> I was able to reproduce Jenkins' failure of
> ServerDisconnect.client_detects_server_shutdown on mako. But only once and not
> repeatably, so can't prove it's due to this branch.

Thanks for trying - I've not been able to reproduce (yet) and your success gives me hope.

As it appears consistently on this branch in CI I'm assuming it is either due to the branch or exposed by it. Either way I need to track it down to land this.

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

> > I was able to reproduce Jenkins' failure of
> > ServerDisconnect.client_detects_server_shutdown on mako. But only once and
> not
> > repeatably, so can't prove it's due to this branch.
>
> Thanks for trying - I've not been able to reproduce (yet) and your success
> gives me hope.
>
> As it appears consistently on this branch in CI I'm assuming it is either due
> to the branch or exposed by it. Either way I need to track it down to land
> this.

Right, I've been able to reproduce and also on *development-branch && desktop*.

This seems to be a race condition in the client side error reporting - something like detecting the broken pipe on the sending thread "before" processing the disconnect event message on the receiving thread.

I've not yet figured out where it breaks, or why this MP is particularly susceptible on the phone. But look for a separate MP.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/client/mir_client_library.cpp'
--- src/client/mir_client_library.cpp 2013-12-18 02:19:19 +0000
+++ src/client/mir_client_library.cpp 2014-01-07 15:59:47 +0000
@@ -108,9 +108,8 @@
108 }108 }
109 catch (std::exception const& x)109 catch (std::exception const& x)
110 {110 {
111 MirConnection* error_connection = new MirConnection();111 MirConnection* error_connection = new MirConnection(x.what());
112 error_connections.insert(error_connection);112 error_connections.insert(error_connection);
113 error_connection->set_error_message(x.what());
114 callback(error_connection, context);113 callback(error_connection, context);
115 return nullptr;114 return nullptr;
116 }115 }
117116
=== modified file 'src/client/mir_connection.cpp'
--- src/client/mir_connection.cpp 2013-12-20 05:06:28 +0000
+++ src/client/mir_connection.cpp 2014-01-07 15:59:47 +0000
@@ -66,10 +66,10 @@
66std::unordered_set<MirConnection*> valid_connections;66std::unordered_set<MirConnection*> valid_connections;
67}67}
6868
69MirConnection::MirConnection() :69MirConnection::MirConnection(std::string const& error_message) :
70 channel(),70 channel(),
71 server(0),71 server(0),
72 error_message("ERROR")72 error_message(error_message)
73{73{
74}74}
7575
@@ -84,11 +84,11 @@
84 lifecycle_control(conf.the_lifecycle_control()),84 lifecycle_control(conf.the_lifecycle_control()),
85 surface_map(conf.the_surface_map())85 surface_map(conf.the_surface_map())
86{86{
87 connect_result.set_error("connect not called");
87 {88 {
88 std::lock_guard<std::mutex> lock(connection_guard);89 std::lock_guard<std::mutex> lock(connection_guard);
89 valid_connections.insert(this);90 valid_connections.insert(this);
90 }91 }
91 connect_result.set_error("connect not called");
92}92}
9393
94MirConnection::~MirConnection() noexcept94MirConnection::~MirConnection() noexcept
@@ -97,9 +97,12 @@
97 // But, if after 500ms we don't get a call, assume it won't happen.97 // But, if after 500ms we don't get a call, assume it won't happen.
98 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));98 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));
9999
100 std::lock_guard<std::mutex> lock(connection_guard);100 {
101 valid_connections.erase(this);101 std::lock_guard<std::mutex> lock(connection_guard);
102 valid_connections.erase(this);
103 }
102104
105 std::lock_guard<decltype(mutex)> lock(mutex);
103 if (connect_result.has_platform())106 if (connect_result.has_platform())
104 {107 {
105 auto const& platform = connect_result.platform();108 auto const& platform = connect_result.platform();
@@ -113,8 +116,6 @@
113 mir_surface_callback callback,116 mir_surface_callback callback,
114 void * context)117 void * context)
115{118{
116 std::lock_guard<std::recursive_mutex> lock(mutex);
117
118 auto surface = new MirSurface(this, server, platform->create_buffer_factory(), input_platform, params, callback, context);119 auto surface = new MirSurface(this, server, platform->create_buffer_factory(), input_platform, params, callback, context);
119120
120 return surface->get_create_wait_handle();121 return surface->get_create_wait_handle();
@@ -122,22 +123,18 @@
122123
123char const * MirConnection::get_error_message()124char const * MirConnection::get_error_message()
124{125{
125 std::lock_guard<std::recursive_mutex> lock(mutex);126 std::lock_guard<decltype(mutex)> lock(mutex);
126127
127 if (connect_result.has_error())128 if (connect_result.has_error())
128 {129 {
129 return connect_result.error().c_str();130 return connect_result.error().c_str();
130 }131 }
131 else132
132 {
133 return error_message.c_str();133 return error_message.c_str();
134 }
135}134}
136135
137void MirConnection::set_error_message(std::string const& error)136void MirConnection::set_error_message(std::string const& error)
138{137{
139 std::lock_guard<std::recursive_mutex> lock(mutex);
140
141 error_message = error;138 error_message = error;
142}139}
143140
@@ -154,10 +151,8 @@
154151
155void MirConnection::released(SurfaceRelease data)152void MirConnection::released(SurfaceRelease data)
156{153{
157 {154 surface_map->erase(data.surface->id());
158 std::lock_guard<std::recursive_mutex> lock(mutex);155
159 surface_map->erase(data.surface->id());
160 }
161 // Erasing this surface from surface_map means that it will no longer receive events156 // Erasing this surface from surface_map means that it will no longer receive events
162 // If it's still focused, send an unfocused event before we kill it entirely157 // If it's still focused, send an unfocused event before we kill it entirely
163 if (data.surface->attrib(mir_surface_attrib_focus) == mir_surface_focused)158 if (data.surface->attrib(mir_surface_attrib_focus) == mir_surface_focused)
@@ -179,8 +174,6 @@
179 mir_surface_callback callback,174 mir_surface_callback callback,
180 void * context)175 void * context)
181{176{
182 std::lock_guard<std::recursive_mutex> lock(mutex);
183
184 auto new_wait_handle = new MirWaitHandle;177 auto new_wait_handle = new MirWaitHandle;
185178
186 SurfaceRelease surf_release{surface, new_wait_handle, callback, context};179 SurfaceRelease surf_release{surface, new_wait_handle, callback, context};
@@ -189,7 +182,7 @@
189 message.set_value(surface->id());182 message.set_value(surface->id());
190183
191 {184 {
192 std::lock_guard<std::mutex> rel_lock(release_wait_handle_guard);185 std::lock_guard<decltype(release_wait_handle_guard)> rel_lock(release_wait_handle_guard);
193 release_wait_handles.push_back(new_wait_handle);186 release_wait_handles.push_back(new_wait_handle);
194 }187 }
195188
@@ -216,7 +209,7 @@
216{209{
217 bool safe_to_callback = true;210 bool safe_to_callback = true;
218 {211 {
219 std::lock_guard<std::recursive_mutex> lock(mutex);212 std::lock_guard<decltype(mutex)> lock(mutex);
220213
221 if (!connect_result.has_platform() || !connect_result.has_display_configuration())214 if (!connect_result.has_platform() || !connect_result.has_display_configuration())
222 {215 {
@@ -248,10 +241,13 @@
248 mir_connected_callback callback,241 mir_connected_callback callback,
249 void * context)242 void * context)
250{243{
251 std::lock_guard<std::recursive_mutex> lock(mutex);244 {
252245 std::lock_guard<decltype(mutex)> lock(mutex);
253 connect_parameters.set_application_name(app_name);246
254 connect_wait_handle.expect_result();247 connect_parameters.set_application_name(app_name);
248 connect_wait_handle.expect_result();
249 }
250
255 server.connect(251 server.connect(
256 0,252 0,
257 &connect_parameters,253 &connect_parameters,
@@ -266,7 +262,7 @@
266 /* todo: keeping all MirWaitHandles from a release surface until the end of the connection262 /* todo: keeping all MirWaitHandles from a release surface until the end of the connection
267 is a kludge until we have a better story about the lifetime of MirWaitHandles */263 is a kludge until we have a better story about the lifetime of MirWaitHandles */
268 {264 {
269 std::lock_guard<std::mutex> lock(release_wait_handle_guard);265 std::lock_guard<decltype(release_wait_handle_guard)> lock(release_wait_handle_guard);
270 for (auto handle : release_wait_handles)266 for (auto handle : release_wait_handles)
271 delete handle;267 delete handle;
272 }268 }
@@ -276,8 +272,6 @@
276272
277MirWaitHandle* MirConnection::disconnect()273MirWaitHandle* MirConnection::disconnect()
278{274{
279 std::lock_guard<std::recursive_mutex> lock(mutex);
280
281 server.disconnect(0, &ignored, &ignored,275 server.disconnect(0, &ignored, &ignored,
282 google::protobuf::NewCallback(this, &MirConnection::done_disconnect));276 google::protobuf::NewCallback(this, &MirConnection::done_disconnect));
283277
@@ -297,8 +291,6 @@
297 mir_drm_auth_magic_callback callback,291 mir_drm_auth_magic_callback callback,
298 void* context)292 void* context)
299{293{
300 std::lock_guard<std::recursive_mutex> lock(mutex);
301
302 mir::protobuf::DRMMagic request;294 mir::protobuf::DRMMagic request;
303 request.set_magic(magic);295 request.set_magic(magic);
304296
@@ -320,12 +312,13 @@
320 return false;312 return false;
321 }313 }
322314
315 std::lock_guard<decltype(connection->mutex)> lock(connection->mutex);
323 return !connection->connect_result.has_error();316 return !connection->connect_result.has_error();
324}317}
325318
326void MirConnection::populate(MirPlatformPackage& platform_package)319void MirConnection::populate(MirPlatformPackage& platform_package)
327{320{
328 std::lock_guard<std::recursive_mutex> lock(mutex);321 std::lock_guard<decltype(mutex)> lock(mutex);
329322
330 if (!connect_result.has_error() && connect_result.has_platform())323 if (!connect_result.has_error() && connect_result.has_platform())
331 {324 {
@@ -351,7 +344,7 @@
351344
352MirDisplayConfiguration* MirConnection::create_copy_of_display_config()345MirDisplayConfiguration* MirConnection::create_copy_of_display_config()
353{346{
354 std::lock_guard<std::recursive_mutex> lock(mutex);347 std::lock_guard<decltype(mutex)> lock(mutex);
355 return display_configuration->copy_to_client();348 return display_configuration->copy_to_client();
356}349}
357350
@@ -361,6 +354,8 @@
361 unsigned int& valid_formats)354 unsigned int& valid_formats)
362{355{
363 valid_formats = 0;356 valid_formats = 0;
357
358 std::lock_guard<decltype(mutex)> lock(mutex);
364 if (!connect_result.has_error())359 if (!connect_result.has_error())
365 {360 {
366 valid_formats = std::min(361 valid_formats = std::min(
@@ -376,7 +371,7 @@
376371
377std::shared_ptr<mir::client::ClientPlatform> MirConnection::get_client_platform()372std::shared_ptr<mir::client::ClientPlatform> MirConnection::get_client_platform()
378{373{
379 std::lock_guard<std::recursive_mutex> lock(mutex);374 std::lock_guard<decltype(mutex)> lock(mutex);
380375
381 return platform;376 return platform;
382}377}
@@ -388,7 +383,7 @@
388383
389EGLNativeDisplayType MirConnection::egl_native_display()384EGLNativeDisplayType MirConnection::egl_native_display()
390{385{
391 std::lock_guard<std::recursive_mutex> lock(mutex);386 std::lock_guard<decltype(mutex)> lock(mutex);
392387
393 return *native_display;388 return *native_display;
394}389}
@@ -410,8 +405,6 @@
410405
411bool MirConnection::validate_user_display_config(MirDisplayConfiguration* config)406bool MirConnection::validate_user_display_config(MirDisplayConfiguration* config)
412{407{
413 std::lock_guard<std::recursive_mutex> lock(mutex);
414
415 MirDisplayConfigurationStore orig_config{display_configuration->copy_to_client()};408 MirDisplayConfigurationStore orig_config{display_configuration->copy_to_client()};
416409
417 if ((!config) || (config->num_outputs == 0) || (config->outputs == NULL) ||410 if ((!config) || (config->num_outputs == 0) || (config->outputs == NULL) ||
@@ -437,6 +430,8 @@
437430
438void MirConnection::done_display_configure()431void MirConnection::done_display_configure()
439{432{
433 std::lock_guard<decltype(mutex)> lock(mutex);
434
440 set_error_message(display_configuration_response.error());435 set_error_message(display_configuration_response.error());
441436
442 if (!display_configuration_response.has_error())437 if (!display_configuration_response.has_error())
@@ -447,23 +442,26 @@
447442
448MirWaitHandle* MirConnection::configure_display(MirDisplayConfiguration* config)443MirWaitHandle* MirConnection::configure_display(MirDisplayConfiguration* config)
449{444{
450 std::lock_guard<std::recursive_mutex> lock(mutex);
451 if (!validate_user_display_config(config))445 if (!validate_user_display_config(config))
452 {446 {
453 return NULL;447 return NULL;
454 }448 }
455449
456 mir::protobuf::DisplayConfiguration request;450 mir::protobuf::DisplayConfiguration request;
457 for (auto i=0u; i < config->num_outputs; i++)
458 {451 {
459 auto output = config->outputs[i];452 std::lock_guard<decltype(mutex)> lock(mutex);
460 auto display_request = request.add_display_output();453
461 display_request->set_output_id(output.output_id);454 for (auto i=0u; i < config->num_outputs; i++)
462 display_request->set_used(output.used);455 {
463 display_request->set_current_mode(output.current_mode);456 auto output = config->outputs[i];
464 display_request->set_position_x(output.position_x);457 auto display_request = request.add_display_output();
465 display_request->set_position_y(output.position_y);458 display_request->set_output_id(output.output_id);
466 display_request->set_power_mode(output.power_mode);459 display_request->set_used(output.used);
460 display_request->set_current_mode(output.current_mode);
461 display_request->set_position_x(output.position_x);
462 display_request->set_position_y(output.position_y);
463 display_request->set_power_mode(output.power_mode);
464 }
467 }465 }
468466
469 server.configure_display(0, &request, &display_configuration_response,467 server.configure_display(0, &request, &display_configuration_response,
@@ -475,6 +473,8 @@
475bool MirConnection::set_extra_platform_data(473bool MirConnection::set_extra_platform_data(
476 std::vector<int> const& extra_platform_data_arg)474 std::vector<int> const& extra_platform_data_arg)
477{475{
476 std::lock_guard<decltype(mutex)> lock(mutex);
477
478 auto const total_data_size =478 auto const total_data_size =
479 connect_result.platform().data_size() + extra_platform_data_arg.size();479 connect_result.platform().data_size() + extra_platform_data_arg.size();
480480
481481
=== modified file 'src/client/mir_connection.h'
--- src/client/mir_connection.h 2013-12-20 05:06:28 +0000
+++ src/client/mir_connection.h 2014-01-07 15:59:47 +0000
@@ -69,7 +69,7 @@
69struct MirConnection : mir::client::ClientContext69struct MirConnection : mir::client::ClientContext
70{70{
71public:71public:
72 MirConnection();72 MirConnection(std::string const& error_message);
7373
74 MirConnection(mir::client::ConnectionConfiguration& conf);74 MirConnection(mir::client::ConnectionConfiguration& conf);
75 ~MirConnection() noexcept;75 ~MirConnection() noexcept;
@@ -87,7 +87,6 @@
87 void *context);87 void *context);
8888
89 char const * get_error_message();89 char const * get_error_message();
90 void set_error_message(std::string const& error);
9190
92 MirWaitHandle* connect(91 MirWaitHandle* connect(
93 const char* app_name,92 const char* app_name,
@@ -125,7 +124,7 @@
125 bool set_extra_platform_data(std::vector<int> const& extra_platform_data);124 bool set_extra_platform_data(std::vector<int> const& extra_platform_data);
126125
127private:126private:
128 std::recursive_mutex mutex; // Protects all members of *this127 std::mutex mutex; // Protects all members of *this (except release_wait_handles)
129128
130 std::shared_ptr<mir::client::rpc::MirBasicRpcChannel> channel;129 std::shared_ptr<mir::client::rpc::MirBasicRpcChannel> channel;
131 mir::protobuf::DisplayServer::Stub server;130 mir::protobuf::DisplayServer::Stub server;
@@ -163,6 +162,7 @@
163162
164 struct SurfaceRelease;163 struct SurfaceRelease;
165164
165 void set_error_message(std::string const& error);
166 void done_disconnect();166 void done_disconnect();
167 void connected(mir_connected_callback callback, void * context);167 void connected(mir_connected_callback callback, void * context);
168 void released(SurfaceRelease );168 void released(SurfaceRelease );
169169
=== modified file 'src/client/mir_surface.cpp'
--- src/client/mir_surface.cpp 2014-01-03 05:37:54 +0000
+++ src/client/mir_surface.cpp 2014-01-07 15:59:47 +0000
@@ -64,7 +64,7 @@
6464
65MirSurface::~MirSurface()65MirSurface::~MirSurface()
66{66{
67 std::lock_guard<std::recursive_mutex> lock(mutex);67 std::lock_guard<decltype(mutex)> lock(mutex);
6868
69 if (input_thread)69 if (input_thread)
70 {70 {
@@ -80,7 +80,7 @@
8080
81MirSurfaceParameters MirSurface::get_parameters() const81MirSurfaceParameters MirSurface::get_parameters() const
82{82{
83 std::lock_guard<std::recursive_mutex> lock(mutex);83 std::lock_guard<decltype(mutex)> lock(mutex);
8484
85 return MirSurfaceParameters {85 return MirSurfaceParameters {
86 0,86 0,
@@ -93,7 +93,7 @@
9393
94char const * MirSurface::get_error_message()94char const * MirSurface::get_error_message()
95{95{
96 std::lock_guard<std::recursive_mutex> lock(mutex);96 std::lock_guard<decltype(mutex)> lock(mutex);
9797
98 if (surface.has_error())98 if (surface.has_error())
99 {99 {
@@ -104,21 +104,21 @@
104104
105int MirSurface::id() const105int MirSurface::id() const
106{106{
107 std::lock_guard<std::recursive_mutex> lock(mutex);107 std::lock_guard<decltype(mutex)> lock(mutex);
108108
109 return surface.id().value();109 return surface.id().value();
110}110}
111111
112bool MirSurface::is_valid() const112bool MirSurface::is_valid() const
113{113{
114 std::lock_guard<std::recursive_mutex> lock(mutex);114 std::lock_guard<decltype(mutex)> lock(mutex);
115115
116 return !surface.has_error();116 return !surface.has_error();
117}117}
118118
119void MirSurface::get_cpu_region(MirGraphicsRegion& region_out)119void MirSurface::get_cpu_region(MirGraphicsRegion& region_out)
120{120{
121 std::lock_guard<std::recursive_mutex> lock(mutex);121 std::lock_guard<decltype(mutex)> lock(mutex);
122122
123 auto buffer = buffer_depository->current_buffer();123 auto buffer = buffer_depository->current_buffer();
124124
@@ -132,21 +132,21 @@
132132
133void MirSurface::release_cpu_region()133void MirSurface::release_cpu_region()
134{134{
135 std::lock_guard<std::recursive_mutex> lock(mutex);
136
137 secured_region.reset();135 secured_region.reset();
138}136}
139137
140MirWaitHandle* MirSurface::next_buffer(mir_surface_callback callback, void * context)138MirWaitHandle* MirSurface::next_buffer(mir_surface_callback callback, void * context)
141{139{
142 std::lock_guard<std::recursive_mutex> lock(mutex);140 std::unique_lock<decltype(mutex)> lock(mutex);
143
144 release_cpu_region();141 release_cpu_region();
142 auto const id = &surface.id();
143 auto const mutable_buffer = surface.mutable_buffer();
144 lock.unlock();
145145
146 server.next_buffer(146 server.next_buffer(
147 0,147 0,
148 &surface.id(),148 id,
149 surface.mutable_buffer(),149 mutable_buffer,
150 google::protobuf::NewCallback(this, &MirSurface::new_buffer, callback, context));150 google::protobuf::NewCallback(this, &MirSurface::new_buffer, callback, context));
151151
152 return &next_buffer_wait_handle;152 return &next_buffer_wait_handle;
@@ -166,8 +166,6 @@
166166
167void MirSurface::process_incoming_buffer()167void MirSurface::process_incoming_buffer()
168{168{
169 std::lock_guard<std::recursive_mutex> lock(mutex);
170
171 auto const& buffer = surface.buffer();169 auto const& buffer = surface.buffer();
172170
173 /*171 /*
@@ -201,17 +199,16 @@
201199
202void MirSurface::created(mir_surface_callback callback, void * context)200void MirSurface::created(mir_surface_callback callback, void * context)
203{201{
202 auto platform = connection->get_client_platform();
203
204 {204 {
205 std::lock_guard<std::recursive_mutex> lock(mutex);205 std::lock_guard<decltype(mutex)> lock(mutex);
206206
207 process_incoming_buffer();207 process_incoming_buffer();
208
209 auto platform = connection->get_client_platform();
210 accelerated_window = platform->create_egl_native_window(this);208 accelerated_window = platform->create_egl_native_window(this);
211
212 connection->on_surface_created(id(), this);
213 }209 }
214210
211 connection->on_surface_created(id(), this);
215 callback(this, context);212 callback(this, context);
216 create_wait_handle.result_received();213 create_wait_handle.result_received();
217}214}
@@ -219,7 +216,7 @@
219void MirSurface::new_buffer(mir_surface_callback callback, void * context)216void MirSurface::new_buffer(mir_surface_callback callback, void * context)
220{217{
221 {218 {
222 std::lock_guard<std::recursive_mutex> lock(mutex);219 std::lock_guard<decltype(mutex)> lock(mutex);
223 process_incoming_buffer();220 process_incoming_buffer();
224 }221 }
225222
@@ -244,23 +241,21 @@
244241
245std::shared_ptr<mcl::ClientBuffer> MirSurface::get_current_buffer()242std::shared_ptr<mcl::ClientBuffer> MirSurface::get_current_buffer()
246{243{
247 std::lock_guard<std::recursive_mutex> lock(mutex);244 std::lock_guard<decltype(mutex)> lock(mutex);
248245
249 return buffer_depository->current_buffer();246 return buffer_depository->current_buffer();
250}247}
251248
252uint32_t MirSurface::get_current_buffer_id() const249uint32_t MirSurface::get_current_buffer_id() const
253{250{
254 std::lock_guard<std::recursive_mutex> lock(mutex);251 std::lock_guard<decltype(mutex)> lock(mutex);
255252
256 return buffer_depository->current_buffer_id();253 return buffer_depository->current_buffer_id();
257}254}
258255
259void MirSurface::populate(MirBufferPackage& buffer_package)256void MirSurface::populate(MirBufferPackage& buffer_package)
260{257{
261 std::lock_guard<std::recursive_mutex> lock(mutex);258 if (!surface.has_error() && surface.has_buffer())
262
263 if (is_valid() && surface.has_buffer())
264 {259 {
265 auto const& buffer = surface.buffer();260 auto const& buffer = surface.buffer();
266261
@@ -292,19 +287,19 @@
292287
293EGLNativeWindowType MirSurface::generate_native_window()288EGLNativeWindowType MirSurface::generate_native_window()
294{289{
295 std::lock_guard<std::recursive_mutex> lock(mutex);290 std::lock_guard<decltype(mutex)> lock(mutex);
296291
297 return *accelerated_window;292 return *accelerated_window;
298}293}
299294
300MirWaitHandle* MirSurface::configure(MirSurfaceAttrib at, int value)295MirWaitHandle* MirSurface::configure(MirSurfaceAttrib at, int value)
301{296{
302 std::lock_guard<std::recursive_mutex> lock(mutex);297 std::unique_lock<decltype(mutex)> lock(mutex);
303
304 mp::SurfaceSetting setting;298 mp::SurfaceSetting setting;
305 setting.mutable_surfaceid()->CopyFrom(surface.id());299 setting.mutable_surfaceid()->CopyFrom(surface.id());
306 setting.set_attrib(at);300 setting.set_attrib(at);
307 setting.set_ivalue(value);301 setting.set_ivalue(value);
302 lock.unlock();
308303
309 configure_wait_handle.expect_result();304 configure_wait_handle.expect_result();
310 server.configure_surface(0, &setting, &configure_result,305 server.configure_surface(0, &setting, &configure_result,
@@ -315,7 +310,7 @@
315310
316void MirSurface::on_configured()311void MirSurface::on_configured()
317{312{
318 std::lock_guard<std::recursive_mutex> lock(mutex);313 std::lock_guard<decltype(mutex)> lock(mutex);
319314
320 if (configure_result.has_surfaceid() &&315 if (configure_result.has_surfaceid() &&
321 configure_result.surfaceid().value() == surface.id().value() &&316 configure_result.surfaceid().value() == surface.id().value() &&
@@ -345,14 +340,14 @@
345340
346int MirSurface::attrib(MirSurfaceAttrib at) const341int MirSurface::attrib(MirSurfaceAttrib at) const
347{342{
348 std::lock_guard<std::recursive_mutex> lock(mutex);343 std::lock_guard<decltype(mutex)> lock(mutex);
349344
350 return attrib_cache[at];345 return attrib_cache[at];
351}346}
352347
353void MirSurface::set_event_handler(MirEventDelegate const* delegate)348void MirSurface::set_event_handler(MirEventDelegate const* delegate)
354{349{
355 std::lock_guard<std::recursive_mutex> lock(mutex);350 std::lock_guard<decltype(mutex)> lock(mutex);
356351
357 if (input_thread)352 if (input_thread)
358 {353 {
@@ -378,7 +373,7 @@
378373
379void MirSurface::handle_event(MirEvent const& e)374void MirSurface::handle_event(MirEvent const& e)
380{375{
381 std::unique_lock<std::recursive_mutex> lock(mutex);376 std::unique_lock<decltype(mutex)> lock(mutex);
382377
383 if (e.type == mir_event_type_surface)378 if (e.type == mir_event_type_surface)
384 {379 {
@@ -397,7 +392,7 @@
397392
398MirPlatformType MirSurface::platform_type()393MirPlatformType MirSurface::platform_type()
399{394{
400 std::lock_guard<std::recursive_mutex> lock(mutex);395 std::lock_guard<decltype(mutex)> lock(mutex);
401396
402 auto platform = connection->get_client_platform();397 auto platform = connection->get_client_platform();
403 return platform->platform_type();398 return platform->platform_type();
404399
=== modified file 'src/client/mir_surface.h'
--- src/client/mir_surface.h 2013-12-18 02:19:19 +0000
+++ src/client/mir_surface.h 2014-01-07 15:59:47 +0000
@@ -83,7 +83,6 @@
83 std::shared_ptr<mir::client::ClientBuffer> get_current_buffer();83 std::shared_ptr<mir::client::ClientBuffer> get_current_buffer();
84 uint32_t get_current_buffer_id() const;84 uint32_t get_current_buffer_id() const;
85 void get_cpu_region(MirGraphicsRegion& region);85 void get_cpu_region(MirGraphicsRegion& region);
86 void release_cpu_region();
87 EGLNativeWindowType generate_native_window();86 EGLNativeWindowType generate_native_window();
8887
89 MirWaitHandle* configure(MirSurfaceAttrib a, int value);88 MirWaitHandle* configure(MirSurfaceAttrib a, int value);
@@ -93,7 +92,7 @@
93 void handle_event(MirEvent const& e);92 void handle_event(MirEvent const& e);
9493
95private:94private:
96 mutable std::recursive_mutex mutex; // Protects all members of *this95 mutable std::mutex mutex; // Protects all members of *this
9796
98 void on_configured();97 void on_configured();
99 void process_incoming_buffer();98 void process_incoming_buffer();
@@ -101,6 +100,7 @@
101 void created(mir_surface_callback callback, void * context);100 void created(mir_surface_callback callback, void * context);
102 void new_buffer(mir_surface_callback callback, void * context);101 void new_buffer(mir_surface_callback callback, void * context);
103 MirPixelFormat convert_ipc_pf_to_geometry(google::protobuf::int32 pf);102 MirPixelFormat convert_ipc_pf_to_geometry(google::protobuf::int32 pf);
103 void release_cpu_region();
104104
105 /* todo: race condition. protobuf does not guarantee that callbacks will be synchronized. potential105 /* todo: race condition. protobuf does not guarantee that callbacks will be synchronized. potential
106 race in surface, last_buffer_id */106 race in surface, last_buffer_id */
@@ -108,7 +108,7 @@
108 mir::protobuf::Surface surface;108 mir::protobuf::Surface surface;
109 std::string error_message;109 std::string error_message;
110110
111 MirConnection *connection;111 MirConnection* const connection;
112 MirWaitHandle create_wait_handle;112 MirWaitHandle create_wait_handle;
113 MirWaitHandle next_buffer_wait_handle;113 MirWaitHandle next_buffer_wait_handle;
114 MirWaitHandle configure_wait_handle;114 MirWaitHandle configure_wait_handle;
115115
=== modified file 'src/client/rpc/mir_basic_rpc_channel.cpp'
--- src/client/rpc/mir_basic_rpc_channel.cpp 2013-09-26 13:23:44 +0000
+++ src/client/rpc/mir_basic_rpc_channel.cpp 2014-01-07 15:59:47 +0000
@@ -33,40 +33,39 @@
33{33{
34}34}
3535
36mclrd::SendBuffer& mclrd::PendingCallCache::save_completion_details(36void mclrd::PendingCallCache::save_completion_details(
37 mir::protobuf::wire::Invocation& invoke,37 mir::protobuf::wire::Invocation& invoke,
38 google::protobuf::Message* response,38 google::protobuf::Message* response,
39 std::shared_ptr<google::protobuf::Closure> const& complete)39 std::shared_ptr<google::protobuf::Closure> const& complete)
40{40{
41 std::unique_lock<std::mutex> lock(mutex);41 std::unique_lock<std::mutex> lock(mutex);
4242
43 auto& current = pending_calls[invoke.id()] = PendingCall(response, complete);43 pending_calls[invoke.id()] = PendingCall(response, complete);
44 return current.send_buffer;
45}44}
4645
47void mclrd::PendingCallCache::complete_response(mir::protobuf::wire::Result& result)46void mclrd::PendingCallCache::complete_response(mir::protobuf::wire::Result& result)
48{47{
49 std::unique_lock<std::mutex> lock(mutex);48 PendingCall completion;
50 auto call = pending_calls.find(result.id());49
51 if (call == pending_calls.end())50 {
51 std::unique_lock<std::mutex> lock(mutex);
52 auto call = pending_calls.find(result.id());
53 if (call != pending_calls.end())
54 {
55 completion = call->second;
56 pending_calls.erase(call);
57 }
58 }
59
60 if (!completion.complete)
52 {61 {
53 rpc_report->orphaned_result(result);62 rpc_report->orphaned_result(result);
54 }63 }
55 else64 else
56 {65 {
57 auto& completion = call->second;
58
59 rpc_report->complete_response(result);66 rpc_report->complete_response(result);
60
61 completion.response->ParseFromString(result.response());67 completion.response->ParseFromString(result.response());
6268 completion.complete->Run();
63 // Let the completion closure live a bit longer than our lock...
64 std::shared_ptr<google::protobuf::Closure> complete =
65 completion.complete;
66 pending_calls.erase(call);
67
68 lock.unlock(); // Avoid deadlocks in callbacks
69 complete->Run();
70 }69 }
71}70}
7271
7372
=== modified file 'src/client/rpc/mir_basic_rpc_channel.h'
--- src/client/rpc/mir_basic_rpc_channel.h 2013-09-26 13:23:44 +0000
+++ src/client/rpc/mir_basic_rpc_channel.h 2014-01-07 15:59:47 +0000
@@ -54,7 +54,7 @@
54public:54public:
55 PendingCallCache(std::shared_ptr<RpcReport> const& rpc_report);55 PendingCallCache(std::shared_ptr<RpcReport> const& rpc_report);
5656
57 SendBuffer& save_completion_details(57 void save_completion_details(
58 mir::protobuf::wire::Invocation& invoke,58 mir::protobuf::wire::Invocation& invoke,
59 google::protobuf::Message* response,59 google::protobuf::Message* response,
60 std::shared_ptr<google::protobuf::Closure> const& complete);60 std::shared_ptr<google::protobuf::Closure> const& complete);
@@ -78,7 +78,6 @@
78 PendingCall()78 PendingCall()
79 : response(0), complete() {}79 : response(0), complete() {}
8080
81 SendBuffer send_buffer;
82 google::protobuf::Message* response;81 google::protobuf::Message* response;
83 std::shared_ptr<google::protobuf::Closure> complete;82 std::shared_ptr<google::protobuf::Closure> complete;
84 };83 };
8584
=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
--- src/client/rpc/mir_socket_rpc_channel.cpp 2013-12-18 02:19:19 +0000
+++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-01-07 15:59:47 +0000
@@ -267,15 +267,14 @@
267 google::protobuf::NewPermanentCallback(this, &MirSocketRpcChannel::receive_file_descriptors, response, complete));267 google::protobuf::NewPermanentCallback(this, &MirSocketRpcChannel::receive_file_descriptors, response, complete));
268268
269 // Only save details after serialization succeeds269 // Only save details after serialization succeeds
270 auto& send_buffer = pending_calls.save_completion_details(invocation, response, callback);270 pending_calls.save_completion_details(invocation, response, callback);
271271
272 // Only send message when details saved for handling response272 // Only send message when details saved for handling response
273 send_message(invocation, send_buffer, invocation);273 send_message(invocation, invocation);
274}274}
275275
276void mclr::MirSocketRpcChannel::send_message(276void mclr::MirSocketRpcChannel::send_message(
277 mir::protobuf::wire::Invocation const& body,277 mir::protobuf::wire::Invocation const& body,
278 detail::SendBuffer& send_buffer,
279 mir::protobuf::wire::Invocation const& invocation)278 mir::protobuf::wire::Invocation const& invocation)
280{279{
281 const size_t size = body.ByteSize();280 const size_t size = body.ByteSize();
@@ -285,7 +284,7 @@
285 static_cast<unsigned char>((size >> 0) & 0xff)284 static_cast<unsigned char>((size >> 0) & 0xff)
286 };285 };
287286
288 send_buffer.resize(sizeof header_bytes + size);287 detail::SendBuffer send_buffer(sizeof header_bytes + size);
289 std::copy(header_bytes, header_bytes + sizeof header_bytes, send_buffer.begin());288 std::copy(header_bytes, header_bytes + sizeof header_bytes, send_buffer.begin());
290 body.SerializeToArray(send_buffer.data() + sizeof header_bytes, size);289 body.SerializeToArray(send_buffer.data() + sizeof header_bytes, size);
291290
292291
=== modified file 'src/client/rpc/mir_socket_rpc_channel.h'
--- src/client/rpc/mir_socket_rpc_channel.h 2013-12-18 02:19:19 +0000
+++ src/client/rpc/mir_socket_rpc_channel.h 2014-01-07 15:59:47 +0000
@@ -83,7 +83,7 @@
8383
84 void receive_file_descriptors(google::protobuf::Message* response, google::protobuf::Closure* complete);84 void receive_file_descriptors(google::protobuf::Message* response, google::protobuf::Closure* complete);
85 void receive_file_descriptors(std::vector<int> &fds);85 void receive_file_descriptors(std::vector<int> &fds);
86 void send_message(mir::protobuf::wire::Invocation const& body, detail::SendBuffer& buffer,86 void send_message(mir::protobuf::wire::Invocation const& body,
87 mir::protobuf::wire::Invocation const& invocation);87 mir::protobuf::wire::Invocation const& invocation);
88 void on_header_read(const boost::system::error_code& error);88 void on_header_read(const boost::system::error_code& error);
8989
9090
=== modified file 'tests/acceptance-tests/test_client_focus_notification.cpp'
--- tests/acceptance-tests/test_client_focus_notification.cpp 2013-12-18 02:19:19 +0000
+++ tests/acceptance-tests/test_client_focus_notification.cpp 2014-01-07 15:59:47 +0000
@@ -136,7 +136,7 @@
136136
137}137}
138138
139TEST_F(BespokeDisplayServerTestFixture, two_scene_are_notified_of_gaining_and_losing_focus)139TEST_F(BespokeDisplayServerTestFixture, two_surfaces_are_notified_of_gaining_and_losing_focus)
140{140{
141 using namespace ::testing;141 using namespace ::testing;
142142

Subscribers

People subscribed via source and target branches