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
=== modified file 'examples/basic.c'
--- examples/basic.c 2014-03-06 06:05:17 +0000
+++ examples/basic.c 2014-07-17 13:57:55 +0000
@@ -88,11 +88,25 @@
88}88}
89///\internal [Callback_tag]89///\internal [Callback_tag]
9090
91MirDemoState mcd = {0, 0};
92
93static void close_connection()
94{
95 if (mcd.connection)
96 {
97 ///\internal [connection_release_tag]
98 mir_connection_release(mcd.connection);
99 puts("Connection released");
100 ///\internal [connection_release_tag]
101 }
102}
103
91void demo_client(const char* server, int buffer_swap_count)104void demo_client(const char* server, int buffer_swap_count)
92{105{
93 MirDemoState mcd;
94 mcd.connection = 0;106 mcd.connection = 0;
95 mcd.surface = 0;107 mcd.surface = 0;
108 // We should always release our connection
109 atexit(&close_connection);
96110
97 puts("Starting");111 puts("Starting");
98112
@@ -182,12 +196,6 @@
182 mir_wait_for(mir_surface_release(mcd.surface, surface_release_callback, &mcd));196 mir_wait_for(mir_surface_release(mcd.surface, surface_release_callback, &mcd));
183 puts("Surface released");197 puts("Surface released");
184 ///\internal [surface_release_tag]198 ///\internal [surface_release_tag]
185
186 ///\internal [connection_release_tag]
187 // We should release our connection
188 mir_connection_release(mcd.connection);
189 puts("Connection released");
190 ///\internal [connection_release_tag]
191}199}
192200
193// The main() function deals with parsing arguments and defaults201// The main() function deals with parsing arguments and defaults
194202
=== modified file 'src/client/android/android_native_display_container.cpp'
--- src/client/android/android_native_display_container.cpp 2014-07-16 16:28:55 +0000
+++ src/client/android/android_native_display_container.cpp 2014-07-17 13:57:55 +0000
@@ -20,16 +20,35 @@
2020
21#include "mir_toolkit/mir_client_library.h"21#include "mir_toolkit/mir_client_library.h"
2222
23#include <mutex>
24
23namespace mcl = mir::client;25namespace mcl = mir::client;
24namespace mcla = mcl::android;26namespace mcla = mcl::android;
2527
26// TODO making this namespace scope extends its life slightly (and avoids a potential crash)28namespace
27// TODO but we should manage it and ensure it is only released after the last connection dies29{
28static mcla::AndroidNativeDisplayContainer default_display_container;30// default_display_container needs to live until the library is unloaded
31std::mutex default_display_container_mutex;
32mcla::AndroidNativeDisplayContainer* default_display_container{nullptr};
33
34extern "C" int __attribute__((destructor)) destroy()
35{
36 std::lock_guard<std::mutex> lock(default_display_container_mutex);
37
38 delete default_display_container;
39
40 return 0;
41}
42}
2943
30mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()44mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()
31{45{
32 return default_display_container;46 std::lock_guard<std::mutex> lock(default_display_container_mutex);
47
48 if (!default_display_container)
49 default_display_container = new mcla::AndroidNativeDisplayContainer;
50
51 return *default_display_container;
33}52}
3453
35mcla::AndroidNativeDisplayContainer::AndroidNativeDisplayContainer()54mcla::AndroidNativeDisplayContainer::AndroidNativeDisplayContainer()
3655
=== modified file 'src/client/connection_configuration.h'
--- src/client/connection_configuration.h 2014-05-29 13:21:08 +0000
+++ src/client/connection_configuration.h 2014-07-17 13:57:55 +0000
@@ -39,8 +39,11 @@
39class Logger;39class Logger;
40}40}
4141
42class SharedLibrary;
43
42namespace client44namespace client
43{45{
46std::shared_ptr<SharedLibrary>& libraries_cache(std::string const& lib_name);
4447
45class ConnectionSurfaceMap;48class ConnectionSurfaceMap;
46class Logger;49class Logger;
@@ -70,7 +73,6 @@
70 ConnectionConfiguration(ConnectionConfiguration const&) = delete;73 ConnectionConfiguration(ConnectionConfiguration const&) = delete;
71 ConnectionConfiguration& operator=(ConnectionConfiguration const&) = delete;74 ConnectionConfiguration& operator=(ConnectionConfiguration const&) = delete;
72};75};
73
74}76}
75}77}
7678
7779
=== modified file 'src/client/default_connection_configuration.cpp'
--- src/client/default_connection_configuration.cpp 2014-07-16 16:28:55 +0000
+++ src/client/default_connection_configuration.cpp 2014-07-17 13:57:55 +0000
@@ -43,15 +43,10 @@
43std::string const lttng_opt_val{"lttng"};43std::string const lttng_opt_val{"lttng"};
44std::string const default_platform_lib{"libmirclientplatform.so"};44std::string const default_platform_lib{"libmirclientplatform.so"};
4545
46// TODO making this namespace scope extends its life slightly (and avoids a potential crash)
47// TODO but we should manage it and ensure it is only released after the last connection dies
48static std::map<std::string, std::shared_ptr<mir::SharedLibrary>> libraries_cache;
49
50mir::SharedLibrary const* load_library(std::string const& libname)46mir::SharedLibrary const* load_library(std::string const& libname)
51{47{
52 // There's no point in loading twice, and it isn't safe to unload...
5348
54 if (auto& ptr = libraries_cache[libname])49 if (auto& ptr = mcl::libraries_cache(libname))
55 {50 {
56 return ptr.get();51 return ptr.get();
57 }52 }
5853
=== modified file 'src/client/mesa/mesa_native_display_container.cpp'
--- src/client/mesa/mesa_native_display_container.cpp 2014-07-16 16:28:55 +0000
+++ src/client/mesa/mesa_native_display_container.cpp 2014-07-17 13:57:55 +0000
@@ -46,15 +46,30 @@
46}46}
4747
48}48}
49}49
5050// default_display_container needs to live until the library is unloaded
51// TODO making this namespace scope extends its life slightly (and avoids a potential crash)51std::mutex default_display_container_mutex;
52// TODO but we should manage it and ensure it is only released after the last connection dies52mclm::MesaNativeDisplayContainer* default_display_container{nullptr};
53static mclm::MesaNativeDisplayContainer default_display_container;53
54extern "C" int __attribute__((destructor)) destroy()
55{
56 std::lock_guard<std::mutex> lock(default_display_container_mutex);
57
58 delete default_display_container;
59
60 return 0;
61}
62}
63
5464
55mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()65mcl::EGLNativeDisplayContainer& mcl::EGLNativeDisplayContainer::instance()
56{66{
57 return default_display_container;67 std::lock_guard<std::mutex> lock(default_display_container_mutex);
68
69 if (!default_display_container)
70 default_display_container = new mclm::MesaNativeDisplayContainer;
71
72 return *default_display_container;
58}73}
5974
60mclm::MesaNativeDisplayContainer::MesaNativeDisplayContainer()75mclm::MesaNativeDisplayContainer::MesaNativeDisplayContainer()
6176
=== modified file 'src/client/mir_connection.cpp'
--- src/client/mir_connection.cpp 2014-07-16 15:10:56 +0000
+++ src/client/mir_connection.cpp 2014-07-17 13:57:55 +0000
@@ -63,11 +63,48 @@
63 MirDisplayConfiguration* const config;63 MirDisplayConfiguration* const config;
64};64};
6565
66using LibrariesCache = std::map<std::string, std::shared_ptr<mir::SharedLibrary>>;
67
66std::mutex connection_guard;68std::mutex connection_guard;
67MirConnection* valid_connections{nullptr};69MirConnection* valid_connections{nullptr};
70// There's no point in loading twice, and it isn't safe to
71// unload while there are valid connections
72std::map<std::string, std::shared_ptr<mir::SharedLibrary>>* libraries_cache_ptr{nullptr};
73}
74
75std::shared_ptr<mir::SharedLibrary>& mcl::libraries_cache(std::string const& libname)
76{
77 std::lock_guard<std::mutex> lock(connection_guard);
78
79 if (!libraries_cache_ptr)
80 libraries_cache_ptr = new LibrariesCache;
81
82 return (*libraries_cache_ptr)[libname];
83}
84
85MirConnection::Deregisterer::~Deregisterer()
86{
87 std::lock_guard<std::mutex> lock(connection_guard);
88
89 for (auto current = &valid_connections; *current; current = &(*current)->next_valid)
90 {
91 if (self == *current)
92 {
93 *current = self->next_valid;
94 break;
95 }
96 }
97
98 // When the last valid connection goes we can clear the libraries cache
99 if (!valid_connections)
100 {
101 delete libraries_cache_ptr;
102 libraries_cache_ptr = nullptr;
103 }
68}104}
69105
70MirConnection::MirConnection(std::string const& error_message) :106MirConnection::MirConnection(std::string const& error_message) :
107 deregisterer{this},
71 channel(),108 channel(),
72 server(0),109 server(0),
73 error_message(error_message)110 error_message(error_message)
@@ -76,6 +113,7 @@
76113
77MirConnection::MirConnection(114MirConnection::MirConnection(
78 mir::client::ConnectionConfiguration& conf) :115 mir::client::ConnectionConfiguration& conf) :
116 deregisterer{this},
79 channel(conf.the_rpc_channel()),117 channel(conf.the_rpc_channel()),
80 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),118 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
81 logger(conf.the_logger()),119 logger(conf.the_logger()),
@@ -100,19 +138,6 @@
100 // But, if after 500ms we don't get a call, assume it won't happen.138 // But, if after 500ms we don't get a call, assume it won't happen.
101 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));139 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));
102140
103 {
104 std::lock_guard<std::mutex> lock(connection_guard);
105
106 for (auto current = &valid_connections; *current; current = &(*current)->next_valid)
107 {
108 if (this == *current)
109 {
110 *current = next_valid;
111 break;
112 }
113 }
114 }
115
116 std::lock_guard<decltype(mutex)> lock(mutex);141 std::lock_guard<decltype(mutex)> lock(mutex);
117 if (connect_result.has_platform())142 if (connect_result.has_platform())
118 {143 {
119144
=== modified file 'src/client/mir_connection.h'
--- src/client/mir_connection.h 2014-07-16 15:10:56 +0000
+++ src/client/mir_connection.h 2014-07-17 13:57:55 +0000
@@ -134,6 +134,10 @@
134 mir::protobuf::DisplayServer& display_server();134 mir::protobuf::DisplayServer& display_server();
135135
136private:136private:
137 // MUST be first data member so it is destroyed last.
138 struct Deregisterer
139 { MirConnection* const self; ~Deregisterer(); } deregisterer;
140
137 std::mutex mutex; // Protects all members of *this (except release_wait_handles)141 std::mutex mutex; // Protects all members of *this (except release_wait_handles)
138142
139 std::shared_ptr<google::protobuf::RpcChannel> const channel;143 std::shared_ptr<google::protobuf::RpcChannel> const channel;

Subscribers

People subscribed via source and target branches

to all changes: