Mir

Merge lp:~mir-team/mir/enable-late-release-0.5-backport into lp:mir/0.5

Proposed by Alan Griffiths
Status: Rejected
Rejected by: Cemil Azizoglu
Proposed branch: lp:~mir-team/mir/enable-late-release-0.5-backport
Merge into: lp:mir/0.5
Diff against target: 269 lines (+105/-37)
7 files modified
examples/basic.c (+15/-7)
src/client/android/android_native_display_container.cpp (+23/-4)
src/client/connection_configuration.h (+3/-1)
src/client/default_connection_configuration.cpp (+1/-6)
src/client/mesa/mesa_native_display_container.cpp (+21/-6)
src/client/mir_connection.cpp (+38/-13)
src/client/mir_connection.h (+4/-0)
To merge this branch: bzr merge lp:~mir-team/mir/enable-late-release-0.5-backport
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir development team Pending
Review via email: mp+227188@code.launchpad.net

Commit message

client: don't allow shared libraries to be unloaded before unity-mir calls connection_release()

Description of the change

client: don't allow shared libraries to be unloaded before unity-mir calls connection_release()

To post a comment you must log in.
1789. By Alan Griffiths

merge -c 1776 lp:~mir-team/mir/enable-late-release

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
Alan Griffiths (alan-griffiths) wrote :

> I: stopping unity8
> Build timed out (after 60 minutes). Marking the build as failed.
> Build was aborted

Looks unrelated - triggering rebuild

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > I: stopping unity8
> > Build timed out (after 60 minutes). Marking the build as failed.
> > Build was aborted
>
> Looks unrelated - triggering rebuild

Hmm. Happened twice on different makos.

Unmerged revisions

1789. By Alan Griffiths

merge -c 1776 lp:~mir-team/mir/enable-late-release

1788. By Alan Griffiths

merge -r1771..1775 lp:~mir-team/mir/enable-late-release

1787. By Alan Griffiths

merge -r1766..1770 lp:~mir-team/mir/enable-late-release

1786. By Alan Griffiths

merge lp:mir/0.5

1785. By Alan Griffiths

TODO notices

1784. By Alan Griffiths

Ensure default_display_container live a bit longer

1783. By Alan Griffiths

Ensure default_display_container live a bit longer

1782. By Alan Griffiths

Ensure loaded libraries live a bit longer

1781. By Alan Griffiths

avoid namespace scope objects

1780. By Daniel van Vugt

Mention another bug fix we forgot - LP: #1189775

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/basic.c'
2--- examples/basic.c 2014-03-06 06:05:17 +0000
3+++ examples/basic.c 2014-07-17 13:57:55 +0000
4@@ -88,11 +88,25 @@
5 }
6 ///\internal [Callback_tag]
7
8+MirDemoState mcd = {0, 0};
9+
10+static void close_connection()
11+{
12+ if (mcd.connection)
13+ {
14+ ///\internal [connection_release_tag]
15+ mir_connection_release(mcd.connection);
16+ puts("Connection released");
17+ ///\internal [connection_release_tag]
18+ }
19+}
20+
21 void demo_client(const char* server, int buffer_swap_count)
22 {
23- MirDemoState mcd;
24 mcd.connection = 0;
25 mcd.surface = 0;
26+ // We should always release our connection
27+ atexit(&close_connection);
28
29 puts("Starting");
30
31@@ -182,12 +196,6 @@
32 mir_wait_for(mir_surface_release(mcd.surface, surface_release_callback, &mcd));
33 puts("Surface released");
34 ///\internal [surface_release_tag]
35-
36- ///\internal [connection_release_tag]
37- // We should release our connection
38- mir_connection_release(mcd.connection);
39- puts("Connection released");
40- ///\internal [connection_release_tag]
41 }
42
43 // The main() function deals with parsing arguments and defaults
44
45=== modified file 'src/client/android/android_native_display_container.cpp'
46--- src/client/android/android_native_display_container.cpp 2014-07-16 16:28:55 +0000
47+++ src/client/android/android_native_display_container.cpp 2014-07-17 13:57:55 +0000
48@@ -20,16 +20,35 @@
49
50 #include "mir_toolkit/mir_client_library.h"
51
52+#include <mutex>
53+
54 namespace mcl = mir::client;
55 namespace mcla = mcl::android;
56
57-// TODO making this namespace scope extends its life slightly (and avoids a potential crash)
58-// TODO but we should manage it and ensure it is only released after the last connection dies
59-static mcla::AndroidNativeDisplayContainer default_display_container;
60+namespace
61+{
62+// default_display_container needs to live until the library is unloaded
63+std::mutex default_display_container_mutex;
64+mcla::AndroidNativeDisplayContainer* default_display_container{nullptr};
65+
66+extern "C" int __attribute__((destructor)) destroy()
67+{
68+ std::lock_guard<std::mutex> lock(default_display_container_mutex);
69+
70+ delete default_display_container;
71+
72+ return 0;
73+}
74+}
75
76 mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()
77 {
78- return default_display_container;
79+ std::lock_guard<std::mutex> lock(default_display_container_mutex);
80+
81+ if (!default_display_container)
82+ default_display_container = new mcla::AndroidNativeDisplayContainer;
83+
84+ return *default_display_container;
85 }
86
87 mcla::AndroidNativeDisplayContainer::AndroidNativeDisplayContainer()
88
89=== modified file 'src/client/connection_configuration.h'
90--- src/client/connection_configuration.h 2014-05-29 13:21:08 +0000
91+++ src/client/connection_configuration.h 2014-07-17 13:57:55 +0000
92@@ -39,8 +39,11 @@
93 class Logger;
94 }
95
96+class SharedLibrary;
97+
98 namespace client
99 {
100+std::shared_ptr<SharedLibrary>& libraries_cache(std::string const& lib_name);
101
102 class ConnectionSurfaceMap;
103 class Logger;
104@@ -70,7 +73,6 @@
105 ConnectionConfiguration(ConnectionConfiguration const&) = delete;
106 ConnectionConfiguration& operator=(ConnectionConfiguration const&) = delete;
107 };
108-
109 }
110 }
111
112
113=== modified file 'src/client/default_connection_configuration.cpp'
114--- src/client/default_connection_configuration.cpp 2014-07-16 16:28:55 +0000
115+++ src/client/default_connection_configuration.cpp 2014-07-17 13:57:55 +0000
116@@ -43,15 +43,10 @@
117 std::string const lttng_opt_val{"lttng"};
118 std::string const default_platform_lib{"libmirclientplatform.so"};
119
120-// TODO making this namespace scope extends its life slightly (and avoids a potential crash)
121-// TODO but we should manage it and ensure it is only released after the last connection dies
122-static std::map<std::string, std::shared_ptr<mir::SharedLibrary>> libraries_cache;
123-
124 mir::SharedLibrary const* load_library(std::string const& libname)
125 {
126- // There's no point in loading twice, and it isn't safe to unload...
127
128- if (auto& ptr = libraries_cache[libname])
129+ if (auto& ptr = mcl::libraries_cache(libname))
130 {
131 return ptr.get();
132 }
133
134=== modified file 'src/client/mesa/mesa_native_display_container.cpp'
135--- src/client/mesa/mesa_native_display_container.cpp 2014-07-16 16:28:55 +0000
136+++ src/client/mesa/mesa_native_display_container.cpp 2014-07-17 13:57:55 +0000
137@@ -46,15 +46,30 @@
138 }
139
140 }
141-}
142-
143-// TODO making this namespace scope extends its life slightly (and avoids a potential crash)
144-// TODO but we should manage it and ensure it is only released after the last connection dies
145-static mclm::MesaNativeDisplayContainer default_display_container;
146+
147+// default_display_container needs to live until the library is unloaded
148+std::mutex default_display_container_mutex;
149+mclm::MesaNativeDisplayContainer* default_display_container{nullptr};
150+
151+extern "C" int __attribute__((destructor)) destroy()
152+{
153+ std::lock_guard<std::mutex> lock(default_display_container_mutex);
154+
155+ delete default_display_container;
156+
157+ return 0;
158+}
159+}
160+
161
162 mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()
163 {
164- return default_display_container;
165+ std::lock_guard<std::mutex> lock(default_display_container_mutex);
166+
167+ if (!default_display_container)
168+ default_display_container = new mclm::MesaNativeDisplayContainer;
169+
170+ return *default_display_container;
171 }
172
173 mclm::MesaNativeDisplayContainer::MesaNativeDisplayContainer()
174
175=== modified file 'src/client/mir_connection.cpp'
176--- src/client/mir_connection.cpp 2014-07-16 15:10:56 +0000
177+++ src/client/mir_connection.cpp 2014-07-17 13:57:55 +0000
178@@ -63,11 +63,48 @@
179 MirDisplayConfiguration* const config;
180 };
181
182+using LibrariesCache = std::map<std::string, std::shared_ptr<mir::SharedLibrary>>;
183+
184 std::mutex connection_guard;
185 MirConnection* valid_connections{nullptr};
186+// There's no point in loading twice, and it isn't safe to
187+// unload while there are valid connections
188+std::map<std::string, std::shared_ptr<mir::SharedLibrary>>* libraries_cache_ptr{nullptr};
189+}
190+
191+std::shared_ptr<mir::SharedLibrary>& mcl::libraries_cache(std::string const& libname)
192+{
193+ std::lock_guard<std::mutex> lock(connection_guard);
194+
195+ if (!libraries_cache_ptr)
196+ libraries_cache_ptr = new LibrariesCache;
197+
198+ return (*libraries_cache_ptr)[libname];
199+}
200+
201+MirConnection::Deregisterer::~Deregisterer()
202+{
203+ std::lock_guard<std::mutex> lock(connection_guard);
204+
205+ for (auto current = &valid_connections; *current; current = &(*current)->next_valid)
206+ {
207+ if (self == *current)
208+ {
209+ *current = self->next_valid;
210+ break;
211+ }
212+ }
213+
214+ // When the last valid connection goes we can clear the libraries cache
215+ if (!valid_connections)
216+ {
217+ delete libraries_cache_ptr;
218+ libraries_cache_ptr = nullptr;
219+ }
220 }
221
222 MirConnection::MirConnection(std::string const& error_message) :
223+ deregisterer{this},
224 channel(),
225 server(0),
226 error_message(error_message)
227@@ -76,6 +113,7 @@
228
229 MirConnection::MirConnection(
230 mir::client::ConnectionConfiguration& conf) :
231+ deregisterer{this},
232 channel(conf.the_rpc_channel()),
233 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
234 logger(conf.the_logger()),
235@@ -100,19 +138,6 @@
236 // But, if after 500ms we don't get a call, assume it won't happen.
237 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));
238
239- {
240- std::lock_guard<std::mutex> lock(connection_guard);
241-
242- for (auto current = &valid_connections; *current; current = &(*current)->next_valid)
243- {
244- if (this == *current)
245- {
246- *current = next_valid;
247- break;
248- }
249- }
250- }
251-
252 std::lock_guard<decltype(mutex)> lock(mutex);
253 if (connect_result.has_platform())
254 {
255
256=== modified file 'src/client/mir_connection.h'
257--- src/client/mir_connection.h 2014-07-16 15:10:56 +0000
258+++ src/client/mir_connection.h 2014-07-17 13:57:55 +0000
259@@ -134,6 +134,10 @@
260 mir::protobuf::DisplayServer& display_server();
261
262 private:
263+ // MUST be first data member so it is destroyed last.
264+ struct Deregisterer
265+ { MirConnection* const self; ~Deregisterer(); } deregisterer;
266+
267 std::mutex mutex; // Protects all members of *this (except release_wait_handles)
268
269 std::shared_ptr<google::protobuf::RpcChannel> const channel;

Subscribers

People subscribed via source and target branches

to all changes: