Mir

Merge lp:~raof/mir/shared-library-prober into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 1900
Proposed branch: lp:~raof/mir/shared-library-prober
Merge into: lp:mir
Diff against target: 939 lines (+726/-2)
19 files modified
CMakeLists.txt (+1/-1)
debian/control (+1/-0)
include.private/common/mir/logging/null_shared_library_prober_report.h (+49/-0)
include.private/common/mir/logging/shared_library_prober_report.h (+48/-0)
include/common/mir/shared_library_prober.h (+36/-0)
include/common/mir/shared_library_prober_report.h (+44/-0)
src/client/default_connection_configuration.cpp (+20/-1)
src/client/default_connection_configuration.h (+4/-0)
src/client/lttng/CMakeLists.txt (+1/-0)
src/client/lttng/shared_library_prober_report.cpp (+50/-0)
src/client/lttng/shared_library_prober_report.h (+55/-0)
src/client/lttng/shared_library_prober_report_tp.h (+85/-0)
src/common/logging/CMakeLists.txt (+1/-0)
src/common/logging/shared_library_prober_report.cpp (+58/-0)
src/common/sharedlibrary/CMakeLists.txt (+1/-0)
src/common/sharedlibrary/shared_library_prober.cpp (+74/-0)
src/common/symbols.map (+9/-0)
tests/unit-tests/CMakeLists.txt (+7/-0)
tests/unit-tests/test_shared_library_prober.cpp (+182/-0)
To merge this branch: bzr merge lp:~raof/mir/shared-library-prober
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alberto Aguirre (community) Approve
Kevin DuBois (community) Approve
Daniel van Vugt Needs Fixing
Cemil Azizoglu (community) Approve
Alexandros Frantzis (community) Approve
Review via email: mp+232516@code.launchpad.net

Commit message

Add a helper to load all the shared libraries in a directory.

While this isn't used yet, it's obviously useful for probing a directory containing platform plugins, which is the follow-on branch.

Description of the change

Start of broken-out privatise-all-the-things.

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
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

923 + EXPECT_TRUE(amd64_failed || armhf_failed);

How come an i386 system can load the amd64 library (it seems to work in the CI tests)? What about arm64, which is one of the architectures we build packages for?

Nits:

37 +mir::libraries_for_path(std::string const& path, mir::SharedLibraryProberReport& report)
638 +{

Perhaps some white space in this function would aid readability.

TEST_F(SharedLibraryProber, ReturnsNonEmptyListForPathContainingLibraries)

I know this (i.e., PascalCase) is supposed to be the right way to name things with GTest but it is a pain to read (IMO, may just be a matter of getting used to it).

review: Needs Information
Revision history for this message
Chris Halse Rogers (raof) wrote :

> 923 + EXPECT_TRUE(amd64_failed || armhf_failed);
>
> How come an i386 system can load the amd64 library (it seems to work in the CI
> tests)? What about arm64, which is one of the architectures we build packages
> for?

And i386 system can't load the amd64 library. But that's fine - for an i386 system (or an arm64 system, or powerpc, or whatever) *both* amd64_failed and armhf_failed will be true. That's not XOR :)

Unless ld.linux gains the ability to load armhf libraries into an x86-64 process or visa versa, at least one of the loads is guaranteed to fail, which means we'll be testing what we want.

>
> Nits:
>
> 37 +mir::libraries_for_path(std::string const& path,
> mir::SharedLibraryProberReport& report)
> 638 +{
>
> Perhaps some white space in this function would aid readability.

Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

OK, the CI failure seems unrelated.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

406 +class SharedLibraryProberReport : public mir::SharedLibraryProberReport

- would be good if the two weren't named exactly the same (makes searching difficult, may confuse some IDEs).

Approved otherwise.

Also, libboost-filesystem-dev had recently been eliminated, now we are reintroducing (which I'm okay with.. just saying).

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

FWIW, SharedLibraryProberReport is consistent with the rest of the mcl::lttng::*Reports - RpcReport, InputReceiverReport, ClientTracepointProvider.

Would you like me to rename all of them, or none of them? :)

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

None of them is fine by me.

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

boost is a giant bloated thing we should be minimizing the use of. I'd much rather see some nice simple dirent logic instead of reintroducing boost::filesystem.

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

I believe that boost::filesystem is standardised in C++14 as the
<filesystem> header (but sadly not yet in our compiler chain), at which
point we basically just drop the boost:: prefix.

Lots of boost is weird and freaky; boost::filesystem isn't really.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I believe that boost::filesystem is standardised in C++14

Unfortunately not, it's just a Technical Specification at the moment. It will hopefully be merged into the next major C++ release (C++17?). Compilers are free to implement the TSs under the std::experimental namespace, but I don't think libstdc++ has any support for it at the moment.

Revision history for this message
Kevin DuBois (kdub) wrote :

#1
789: binary_path()
I had to use this functionality last month in a different test, so I split out mtf::executable_path(). We should reuse that.

#2
My concern about using boost filesystem is more that it increases the touch image size... However it seems to already be there so I don't mind using it.

'preapproving', pending fixing #1

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote :

#1
Hah! And I extend mtf::executable_path() in the follow up branch. I clearly didn't pull it back when splitting this out though. Fixed.

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
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

CI was aborted so unrelated.

Looks good to me.

Nit:

837 + // /usr is guaranteed to exist, and shouldn't contain any libraries

Would be nice if there was an expectation or assertion to test that assumption, or perhaps create a temp directory under /tmp?

review: Approve
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: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Daniel: are you still blocking over boost-filesystem? I mean, I can implement a subset std::experimental::filesystem using dirent if you really want... :)

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

It's a minor regression in terms of bloat and portability. But I know when I've been outvoted. Top-approving despite my disapproval on principle.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-09-05 03:37:19 +0000
3+++ CMakeLists.txt 2014-09-08 04:22:15 +0000
4@@ -107,7 +107,7 @@
5 include_directories(include/common include.private/common)
6
7 # Check for boost
8-find_package(Boost 1.48.0 COMPONENTS date_time system program_options iostreams REQUIRED)
9+find_package(Boost 1.48.0 COMPONENTS date_time system program_options iostreams filesystem REQUIRED)
10 include_directories (
11 ${Boost_INCLUDE_DIRS}
12 )
13
14=== modified file 'debian/control'
15--- debian/control 2014-09-05 03:37:19 +0000
16+++ debian/control 2014-09-08 04:22:15 +0000
17@@ -19,6 +19,7 @@
18 libboost-program-options-dev,
19 libboost-system-dev,
20 libboost-iostreams-dev,
21+ libboost-filesystem-dev,
22 protobuf-compiler,
23 libdrm-dev,
24 libegl1-mesa-dev,
25
26=== added file 'include.private/common/mir/logging/null_shared_library_prober_report.h'
27--- include.private/common/mir/logging/null_shared_library_prober_report.h 1970-01-01 00:00:00 +0000
28+++ include.private/common/mir/logging/null_shared_library_prober_report.h 2014-09-08 04:22:15 +0000
29@@ -0,0 +1,49 @@
30+/*
31+ * Copyright © 2014 Canonical Ltd.
32+ *
33+ * This program is free software: you can redistribute it and/or modify
34+ * it under the terms of the GNU Lesser General Public License version 3 as
35+ * published by the Free Software Foundation.
36+ *
37+ * This program is distributed in the hope that it will be useful,
38+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
39+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40+ * GNU Lesser General Public License for more details.
41+ *
42+ * You should have received a copy of the GNU Lesser General Public License
43+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
44+ *
45+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
46+ */
47+
48+#ifndef MIR_LOGGING_NULL_SHARED_LIBRARY_PROBER_REPORT_H_
49+#define MIR_LOGGING_NULL_SHARED_LIBRARY_PROBER_REPORT_H_
50+
51+#include "mir/shared_library_prober_report.h"
52+
53+namespace mir
54+{
55+namespace logging
56+{
57+
58+class NullSharedLibraryProberReport : public mir::SharedLibraryProberReport
59+{
60+public:
61+ void probing_path(boost::filesystem::path const& /*path*/) override
62+ {
63+ }
64+ void probing_failed(boost::filesystem::path const& /*path*/, std::exception const& /*error*/) override
65+ {
66+ }
67+ void loading_library(boost::filesystem::path const& /*filename*/) override
68+ {
69+ }
70+ void loading_failed(boost::filesystem::path const& /*filename*/, std::exception const& /*error*/) override
71+ {
72+ }
73+};
74+
75+}
76+}
77+
78+#endif /* MIR_LOGGING_NULL_SHARED_LIBRARY_PROBER_REPORT_H_ */
79
80=== added file 'include.private/common/mir/logging/shared_library_prober_report.h'
81--- include.private/common/mir/logging/shared_library_prober_report.h 1970-01-01 00:00:00 +0000
82+++ include.private/common/mir/logging/shared_library_prober_report.h 2014-09-08 04:22:15 +0000
83@@ -0,0 +1,48 @@
84+/*
85+ * Copyright © 2014 Canonical Ltd.
86+ *
87+ * This program is free software: you can redistribute it and/or modify
88+ * it under the terms of the GNU Lesser General Public License version 3 as
89+ * published by the Free Software Foundation.
90+ *
91+ * This program is distributed in the hope that it will be useful,
92+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
93+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94+ * GNU Lesser General Public License for more details.
95+ *
96+ * You should have received a copy of the GNU Lesser General Public License
97+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
98+ *
99+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
100+ */
101+
102+#ifndef MIR_LOGGING_SHARED_LIBRARY_PROBER_REPORT_H_
103+#define MIR_LOGGING_SHARED_LIBRARY_PROBER_REPORT_H_
104+
105+#include "mir/shared_library_prober_report.h"
106+#include <memory>
107+
108+namespace mir
109+{
110+namespace logging
111+{
112+class Logger;
113+
114+class SharedLibraryProberReport : public mir::SharedLibraryProberReport
115+{
116+public:
117+ SharedLibraryProberReport(std::shared_ptr<Logger> const& logger);
118+
119+ void probing_path(boost::filesystem::path const& path) override;
120+ void probing_failed(boost::filesystem::path const& path, std::exception const& error) override;
121+ void loading_library(boost::filesystem::path const& filename) override;
122+ void loading_failed(boost::filesystem::path const& filename, std::exception const& error) override;
123+
124+private:
125+ std::shared_ptr<Logger> const logger;
126+};
127+
128+}
129+}
130+
131+#endif /* MIR_LOGGING_SHARED_LIBRARY_PROBER_REPORT_H_ */
132
133=== added file 'include/common/mir/shared_library_prober.h'
134--- include/common/mir/shared_library_prober.h 1970-01-01 00:00:00 +0000
135+++ include/common/mir/shared_library_prober.h 2014-09-08 04:22:15 +0000
136@@ -0,0 +1,36 @@
137+/*
138+ * Copyright © 2014 Canonical Ltd.
139+ *
140+ * This program is free software: you can redistribute it and/or modify it
141+ * under the terms of the GNU Lesser General Public License version 3,
142+ * as published by the Free Software Foundation.
143+ *
144+ * This program is distributed in the hope that it will be useful,
145+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
146+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147+ * GNU Lesser General Public License for more details.
148+ *
149+ * You should have received a copy of the GNU Lesser General Public License
150+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
151+ *
152+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
153+ */
154+
155+#ifndef MIR_SHARED_LIBRARY_PROBER_H_
156+#define MIR_SHARED_LIBRARY_PROBER_H_
157+
158+#include "shared_library_prober_report.h"
159+
160+#include <string>
161+#include <vector>
162+#include <memory>
163+
164+namespace mir
165+{
166+class SharedLibrary;
167+
168+std::vector<std::shared_ptr<SharedLibrary>> libraries_for_path(std::string const& path, SharedLibraryProberReport& report);
169+}
170+
171+
172+#endif /* MIR_SHARED_LIBRARY_PROBER_H_ */
173
174=== added file 'include/common/mir/shared_library_prober_report.h'
175--- include/common/mir/shared_library_prober_report.h 1970-01-01 00:00:00 +0000
176+++ include/common/mir/shared_library_prober_report.h 2014-09-08 04:22:15 +0000
177@@ -0,0 +1,44 @@
178+/*
179+ * Copyright © 2014 Canonical Ltd.
180+ *
181+ * This program is free software: you can redistribute it and/or modify it
182+ * under the terms of the GNU Lesser General Public License version 3,
183+ * as published by the Free Software Foundation.
184+ *
185+ * This program is distributed in the hope that it will be useful,
186+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
187+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
188+ * GNU Lesser General Public License for more details.
189+ *
190+ * You should have received a copy of the GNU Lesser General Public License
191+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
192+ *
193+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
194+ */
195+
196+#ifndef MIR_SHARED_LIBRARY_PROBER_REPORT_H_
197+#define MIR_SHARED_LIBRARY_PROBER_REPORT_H_
198+
199+#include <boost/filesystem.hpp>
200+
201+namespace mir
202+{
203+class SharedLibraryProberReport
204+{
205+public:
206+ virtual ~SharedLibraryProberReport() = default;
207+
208+ virtual void probing_path(boost::filesystem::path const& path) = 0;
209+ virtual void probing_failed(boost::filesystem::path const& path, std::exception const& error) = 0;
210+ virtual void loading_library(boost::filesystem::path const& filename) = 0;
211+ virtual void loading_failed(boost::filesystem::path const& filename, std::exception const& error) = 0;
212+
213+protected:
214+ SharedLibraryProberReport() = default;
215+ SharedLibraryProberReport(SharedLibraryProberReport const&) = delete;
216+ SharedLibraryProberReport& operator=(SharedLibraryProberReport const&) = delete;
217+};
218+}
219+
220+
221+#endif /* MIR_SHARED_LIBRARY_PROBER_REPORT_H_ */
222
223=== modified file 'src/client/default_connection_configuration.cpp'
224--- src/client/default_connection_configuration.cpp 2014-09-05 03:37:19 +0000
225+++ src/client/default_connection_configuration.cpp 2014-09-08 04:22:15 +0000
226@@ -26,13 +26,17 @@
227 #include "mir/input/null_input_receiver_report.h"
228 #include "logging/rpc_report.h"
229 #include "logging/input_receiver_report.h"
230+#include "mir/logging/shared_library_prober_report.h"
231+#include "mir/logging/null_shared_library_prober_report.h"
232 #include "lttng/rpc_report.h"
233 #include "lttng/input_receiver_report.h"
234+#include "lttng/shared_library_prober_report.h"
235 #include "connection_surface_map.h"
236 #include "lifecycle_control.h"
237 #include "mir/shared_library.h"
238 #include "client_platform_factory.h"
239 #include "mir_event_distributor.h"
240+#include "mir/shared_library_prober.h"
241
242 #include <dlfcn.h>
243
244@@ -197,6 +201,22 @@
245 });
246 }
247
248+std::shared_ptr<mir::SharedLibraryProberReport> mir::client::DefaultConnectionConfiguration::the_shared_library_prober_report()
249+{
250+ return shared_library_prober_report(
251+ [this] () -> std::shared_ptr<mir::SharedLibraryProberReport>
252+ {
253+ auto val_raw = getenv("MIR_CLIENT_SHARED_LIBRARY_PROBER_REPORT");
254+ std::string const val{val_raw ? val_raw : off_opt_val};
255+ if (val == log_opt_val)
256+ return std::make_shared<mir::logging::SharedLibraryProberReport>(the_logger());
257+ else if (val == lttng_opt_val)
258+ return std::make_shared<mcl::lttng::SharedLibraryProberReport>();
259+ else
260+ return std::make_shared<mir::logging::NullSharedLibraryProberReport>();
261+ });
262+}
263+
264 std::shared_ptr<mir::SharedLibrary> mcl::DefaultConnectionConfiguration::the_platform_library()
265 {
266 if (!platform_library)
267@@ -206,6 +226,5 @@
268 std::string const libname{val_raw ? val_raw : default_platform_lib};
269 platform_library = std::make_shared<mir::SharedLibrary>(libname);
270 }
271-
272 return platform_library;
273 }
274
275=== modified file 'src/client/default_connection_configuration.h'
276--- src/client/default_connection_configuration.h 2014-09-05 03:37:19 +0000
277+++ src/client/default_connection_configuration.h 2014-09-08 04:22:15 +0000
278@@ -27,6 +27,8 @@
279
280 namespace mir
281 {
282+class SharedLibraryProberReport;
283+
284 namespace input
285 {
286 namespace receiver
287@@ -57,6 +59,7 @@
288 std::shared_ptr<LifecycleControl> the_lifecycle_control();
289 std::shared_ptr<EventSink> the_event_sink();
290 std::shared_ptr<EventHandlerRegister> the_event_handler_register();
291+ std::shared_ptr<mir::SharedLibraryProberReport> the_shared_library_prober_report();
292 std::shared_ptr<SharedLibrary> the_platform_library() override;
293
294 virtual std::string the_socket_file();
295@@ -78,6 +81,7 @@
296
297 CachedPtr<rpc::RpcReport> rpc_report;
298 CachedPtr<input::receiver::InputReceiverReport> input_receiver_report;
299+ CachedPtr<mir::SharedLibraryProberReport> shared_library_prober_report;
300
301 private:
302 std::string const socket_file;
303
304=== modified file 'src/client/lttng/CMakeLists.txt'
305--- src/client/lttng/CMakeLists.txt 2014-09-05 03:37:19 +0000
306+++ src/client/lttng/CMakeLists.txt 2014-09-08 04:22:15 +0000
307@@ -6,6 +6,7 @@
308 client_tracepoint_provider.cpp
309 rpc_report.cpp
310 input_receiver_report.cpp
311+ shared_library_prober_report.cpp
312 )
313
314 add_library(mirclientlttng SHARED tracepoints.c)
315
316=== added file 'src/client/lttng/shared_library_prober_report.cpp'
317--- src/client/lttng/shared_library_prober_report.cpp 1970-01-01 00:00:00 +0000
318+++ src/client/lttng/shared_library_prober_report.cpp 2014-09-08 04:22:15 +0000
319@@ -0,0 +1,50 @@
320+/*
321+ * Copyright © 2014 Canonical Ltd.
322+ *
323+ * This program is free software: you can redistribute it and/or modify
324+ * it under the terms of the GNU Lesser General Public License version 3 as
325+ * published by the Free Software Foundation.
326+ *
327+ * This program is distributed in the hope that it will be useful,
328+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
329+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
330+ * GNU Lesser General Public License for more details.
331+ *
332+ * You should have received a copy of the GNU Lesser General Public License
333+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
334+ *
335+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
336+ */
337+
338+#include "shared_library_prober_report.h"
339+#include "mir/report/lttng/mir_tracepoint.h"
340+
341+#define TRACEPOINT_DEFINE
342+#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
343+#include "shared_library_prober_report_tp.h"
344+
345+namespace mcl = mir::client;
346+
347+void mcl::lttng::SharedLibraryProberReport::probing_path(boost::filesystem::path const& path)
348+{
349+ mir_tracepoint(mir_client_shared_library_prober, probing_path,
350+ path.string().c_str());
351+}
352+
353+void mcl::lttng::SharedLibraryProberReport::probing_failed(boost::filesystem::path const& path, std::exception const& error)
354+{
355+ mir_tracepoint(mir_client_shared_library_prober, probing_failed,
356+ path.string().c_str(), error.what());
357+}
358+
359+void mcl::lttng::SharedLibraryProberReport::loading_library(boost::filesystem::path const& filename)
360+{
361+ mir_tracepoint(mir_client_shared_library_prober, loading_library,
362+ filename.string().c_str());
363+}
364+
365+void mcl::lttng::SharedLibraryProberReport::loading_failed(boost::filesystem::path const& filename, std::exception const& error)
366+{
367+ mir_tracepoint(mir_client_shared_library_prober, loading_failed,
368+ filename.string().c_str(), error.what());
369+}
370
371=== added file 'src/client/lttng/shared_library_prober_report.h'
372--- src/client/lttng/shared_library_prober_report.h 1970-01-01 00:00:00 +0000
373+++ src/client/lttng/shared_library_prober_report.h 2014-09-08 04:22:15 +0000
374@@ -0,0 +1,55 @@
375+/*
376+ * Copyright © 2014 Canonical Ltd.
377+ *
378+ * This program is free software: you can redistribute it and/or modify
379+ * it under the terms of the GNU Lesser General Public License version 3 as
380+ * published by the Free Software Foundation.
381+ *
382+ * This program is distributed in the hope that it will be useful,
383+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
384+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
385+ * GNU Lesser General Public License for more details.
386+ *
387+ * You should have received a copy of the GNU Lesser General Public License
388+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
389+ *
390+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
391+ */
392+
393+#ifndef MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_H_
394+#define MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_H_
395+
396+#include "mir/shared_library_prober_report.h"
397+#include "client_tracepoint_provider.h"
398+
399+namespace mir
400+{
401+namespace client
402+{
403+namespace lttng
404+{
405+
406+class SharedLibraryProberReport : public mir::SharedLibraryProberReport
407+{
408+public:
409+ void probing_path(boost::filesystem::path const& path) override;
410+ void probing_failed(boost::filesystem::path const& path, std::exception const& error) override;
411+ void loading_library(boost::filesystem::path const& filename) override;
412+ void loading_failed(boost::filesystem::path const& filename, std::exception const& error) override;
413+
414+private:
415+ ClientTracepointProvider tp_provider;
416+};
417+
418+}
419+}
420+}
421+
422+#endif /* MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_H_ */
423+
424+
425+#ifndef SHARED_LIBRARY_PROBER_REPORT_H
426+#define SHARED_LIBRARY_PROBER_REPORT_H
427+
428+
429+#endif // SHARED_LIBRARY_PROBER_REPORT_H
430
431=== added file 'src/client/lttng/shared_library_prober_report_tp.h'
432--- src/client/lttng/shared_library_prober_report_tp.h 1970-01-01 00:00:00 +0000
433+++ src/client/lttng/shared_library_prober_report_tp.h 2014-09-08 04:22:15 +0000
434@@ -0,0 +1,85 @@
435+/*
436+ * Copyright © 2014 Canonical Ltd.
437+ *
438+ * This program is free software: you can redistribute it and/or modify
439+ * it under the terms of the GNU Lesser General Public License version 3 as
440+ * published by the Free Software Foundation.
441+ *
442+ * This program is distributed in the hope that it will be useful,
443+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
444+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
445+ * GNU Lesser General Public License for more details.
446+ *
447+ * You should have received a copy of the GNU Lesser General Public License
448+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
449+ *
450+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
451+ */
452+
453+#undef TRACEPOINT_PROVIDER
454+#define TRACEPOINT_PROVIDER mir_client_shared_library_prober
455+
456+#undef TRACEPOINT_INCLUDE
457+#define TRACEPOINT_INCLUDE "./shared_library_prober_report_tp.h"
458+
459+#if !defined(MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_TP_H_) || defined(TRACEPOINT_HEADER_MULTI_READ)
460+#define MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_TP_H_
461+
462+#include <lttng/tracepoint.h>
463+#include <stdint.h>
464+
465+#ifdef __clang__
466+/*
467+ * TRACEPOINT_EVENT defines functions; since we disable tracepoints under clang
468+ * these functions are unused and so generate fatal warnings.
469+ * (see mir_tracepoint.h and http://sourceware.org/bugzilla/show_bug.cgi?id=13974)
470+ */
471+#pragma clang diagnostic push
472+#pragma clang diagnostic warning "-Wunused-function"
473+#endif
474+
475+TRACEPOINT_EVENT(
476+ mir_client_shared_library_prober,
477+ probing_path,
478+ TP_ARGS(const char*, path),
479+ TP_FIELDS(
480+ ctf_string(path, path)
481+ )
482+)
483+
484+TRACEPOINT_EVENT(
485+ mir_client_shared_library_prober,
486+ probing_failed,
487+ TP_ARGS(const char*, path, const char*, message),
488+ TP_FIELDS(
489+ ctf_string(path, path)
490+ ctf_string(message, message)
491+ )
492+)
493+
494+TRACEPOINT_EVENT(
495+ mir_client_shared_library_prober,
496+ loading_library,
497+ TP_ARGS(const char*, path),
498+ TP_FIELDS(
499+ ctf_string(path, path)
500+ )
501+)
502+
503+TRACEPOINT_EVENT(
504+ mir_client_shared_library_prober,
505+ loading_failed,
506+ TP_ARGS(const char*, path, const char*, message),
507+ TP_FIELDS(
508+ ctf_string(path, path)
509+ ctf_string(message, message)
510+ )
511+)
512+
513+#ifdef __clang__
514+#pragma clang diagnostic pop
515+#endif
516+
517+#endif /* MIR_CLIENT_LTTNG_SHARED_LIBRARY_PROBER_REPORT_TP_H_ */
518+
519+#include <lttng/tracepoint-event.h>
520
521=== modified file 'src/common/logging/CMakeLists.txt'
522--- src/common/logging/CMakeLists.txt 2014-09-05 03:37:19 +0000
523+++ src/common/logging/CMakeLists.txt 2014-09-08 04:22:15 +0000
524@@ -17,6 +17,7 @@
525 add_library(mirsharedlogging OBJECT
526 dumb_console_logger.cpp
527 input_timestamp.cpp
528+ shared_library_prober_report.cpp
529 )
530
531 list(APPEND MIR_COMMON_SOURCES
532
533=== added file 'src/common/logging/shared_library_prober_report.cpp'
534--- src/common/logging/shared_library_prober_report.cpp 1970-01-01 00:00:00 +0000
535+++ src/common/logging/shared_library_prober_report.cpp 2014-09-08 04:22:15 +0000
536@@ -0,0 +1,58 @@
537+
538+/*
539+ * Copyright © 2014 Canonical Ltd.
540+ *
541+ * This program is free software: you can redistribute it and/or modify
542+ * it under the terms of the GNU Lesser General Public License version 3 as
543+ * published by the Free Software Foundation.
544+ *
545+ * This program is distributed in the hope that it will be useful,
546+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
547+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
548+ * GNU Lesser General Public License for more details.
549+ *
550+ * You should have received a copy of the GNU Lesser General Public License
551+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
552+ *
553+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
554+ */
555+
556+#include "mir/logging/shared_library_prober_report.h"
557+#include "mir/logging/logger.h"
558+
559+namespace ml = mir::logging;
560+
561+ml::SharedLibraryProberReport::SharedLibraryProberReport(std::shared_ptr<Logger> const& logger)
562+ : logger{logger}
563+{
564+}
565+
566+void ml::SharedLibraryProberReport::probing_path(boost::filesystem::path const& path)
567+{
568+ logger->log(ml::Logger::Severity::informational,
569+ std::string("Loading modules from: ") + path.string(),
570+ "Loader");
571+}
572+
573+void ml::SharedLibraryProberReport::probing_failed(boost::filesystem::path const& path, std::exception const& error)
574+{
575+ logger->log(ml::Logger::Severity::error,
576+ std::string("Failed to load libraries from path: ") + path.string() +
577+ " (error was:" + error.what() + ")",
578+ "Loader");
579+}
580+
581+void ml::SharedLibraryProberReport::loading_library(boost::filesystem::path const& filename)
582+{
583+ logger->log(ml::Logger::Severity::informational,
584+ std::string("Loading module: ") + filename.string(),
585+ "Loader");
586+}
587+
588+void ml::SharedLibraryProberReport::loading_failed(boost::filesystem::path const& filename, std::exception const& error)
589+{
590+ logger->log(ml::Logger::Severity::warning,
591+ std::string("Failed to load module: ") + filename.string() +
592+ " (error was:" + error.what() + ")",
593+ "Loader");
594+}
595
596=== modified file 'src/common/sharedlibrary/CMakeLists.txt'
597--- src/common/sharedlibrary/CMakeLists.txt 2014-09-05 03:37:19 +0000
598+++ src/common/sharedlibrary/CMakeLists.txt 2014-09-08 04:22:15 +0000
599@@ -16,6 +16,7 @@
600
601 add_library(mirsharedsharedlibrary OBJECT
602 shared_library.cpp
603+ shared_library_prober.cpp
604 )
605
606 list(APPEND MIR_COMMON_SOURCES
607
608=== added file 'src/common/sharedlibrary/shared_library_prober.cpp'
609--- src/common/sharedlibrary/shared_library_prober.cpp 1970-01-01 00:00:00 +0000
610+++ src/common/sharedlibrary/shared_library_prober.cpp 2014-09-08 04:22:15 +0000
611@@ -0,0 +1,74 @@
612+/*
613+ * Copyright © 2014 Canonical Ltd.
614+ *
615+ * This program is free software: you can redistribute it and/or modify it
616+ * under the terms of the GNU Lesser General Public License version 3,
617+ * as published by the Free Software Foundation.
618+ *
619+ * This program is distributed in the hope that it will be useful,
620+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
621+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
622+ * GNU Lesser General Public License for more details.
623+ *
624+ * You should have received a copy of the GNU Lesser General Public License
625+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
626+ *
627+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
628+ */
629+
630+#include "mir/shared_library_prober.h"
631+#include "mir/shared_library.h"
632+
633+#include <system_error>
634+#include <boost/filesystem.hpp>
635+
636+namespace
637+{
638+std::error_code boost_to_std_error(boost::system::error_code const& ec)
639+{
640+ if (ec)
641+ {
642+ if (ec.category() != boost::system::system_category())
643+ {
644+ throw std::logic_error{"Boost error from unexpected category: " +
645+ ec.message()};
646+ }
647+ return std::error_code{ec.value(), std::system_category()};
648+ }
649+ return std::error_code{};
650+}
651+}
652+
653+std::vector<std::shared_ptr<mir::SharedLibrary>>
654+mir::libraries_for_path(std::string const& path, mir::SharedLibraryProberReport& report)
655+{
656+ report.probing_path(path);
657+ // We use the error_code overload because we want to throw a std::system_error
658+ boost::system::error_code ec;
659+
660+ boost::filesystem::directory_iterator iterator{path, ec};
661+ if (ec)
662+ {
663+ std::system_error error{boost_to_std_error(ec)};
664+ report.probing_failed(path, error);
665+ throw error;
666+ }
667+
668+ std::vector<std::shared_ptr<mir::SharedLibrary>> libraries;
669+ for (; iterator != boost::filesystem::directory_iterator() ; ++iterator)
670+ {
671+ if (iterator->path().extension().string() == ".so")
672+ {
673+ try
674+ {
675+ report.loading_library(iterator->path());
676+ libraries.emplace_back(std::make_shared<mir::SharedLibrary>(iterator->path().string()));
677+ }
678+ catch (std::runtime_error const& err)
679+ {
680+ report.loading_failed(iterator->path(), err);
681+ }
682+ }
683+ }
684+ return libraries;
685+}
686
687=== modified file 'src/common/symbols.map'
688--- src/common/symbols.map 2014-09-05 06:22:08 +0000
689+++ src/common/symbols.map 2014-09-08 04:22:15 +0000
690@@ -130,12 +130,19 @@
691 mir::input::receiver::XKBMapper::update_state_and_map_event*;
692 mir::input::receiver::XKBMapper::?XKBMapper*;
693 mir::input::receiver::XKBMapper::XKBMapper*;
694+ mir::libraries_for_path*;
695 mir::logging::DumbConsoleLogger::log*;
696 mir::logging::input_timestamp*;
697 mir::logging::Logger::log*;
698 mir::logging::Logger::?Logger*;
699 mir::logging::Logger::Logger*;
700 mir::logging::Logger::operator*;
701+ mir::logging::SharedLibraryProberReport::?SharedLibraryProberReport*;
702+ mir::logging::SharedLibraryProberReport::SharedLibraryProberReport*;
703+ mir::logging::SharedLibraryProberReport::probing_path*;
704+ mir::logging::SharedLibraryProberReport::probing_failed*;
705+ mir::logging::SharedLibraryProberReport::loading_library*;
706+ mir::logging::SharedLibraryProberReport::loading_failed*;
707 mir_omnidirectional_resize_cursor_name*;
708 mir_open_hand_cursor_name*;
709 mir_pointing_hand_cursor_name*;
710@@ -807,6 +814,7 @@
711 typeinfo?for?MirKeyEvent;
712 typeinfo?for?mir::logging::DumbConsoleLogger;
713 typeinfo?for?mir::logging::Logger;
714+ typeinfo?for?mir::logging::SharedLibraryProberReport;
715 typeinfo?for?MirMesaEGLNativeDisplay;
716 typeinfo?for?MirMesaEGLNativeSurface;
717 typeinfo?for?MirMotionEvent;
718@@ -899,6 +907,7 @@
719 vtable?for?MirKeyEvent;
720 vtable?for?mir::logging::DumbConsoleLogger;
721 vtable?for?mir::logging::Logger;
722+ vtable?for?mir::logging::SharedLibraryProberReport;
723 vtable?for?MirMesaEGLNativeDisplay;
724 vtable?for?MirMesaEGLNativeSurface;
725 vtable?for?MirMotionEvent;
726
727=== modified file 'tests/unit-tests/CMakeLists.txt'
728--- tests/unit-tests/CMakeLists.txt 2014-09-05 03:37:19 +0000
729+++ tests/unit-tests/CMakeLists.txt 2014-09-08 04:22:15 +0000
730@@ -21,6 +21,7 @@
731 test_basic_observers.cpp
732 test_fatal.cpp
733 test_fd.cpp
734+ test_shared_library_prober.cpp
735 )
736
737 add_subdirectory(options/)
738@@ -106,3 +107,9 @@
739 TARGETS mir_unit_tests
740 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
741 )
742+
743+add_custom_command(TARGET mir_unit_tests POST_BUILD
744+ COMMAND ${CMAKE_COMMAND} -E copy_directory
745+ ${CMAKE_CURRENT_SOURCE_DIR}/test_data ${CMAKE_BINARY_DIR}/bin/test_data
746+ COMMENT "Copying test data to build dir..."
747+)
748
749=== added directory 'tests/unit-tests/test_data'
750=== added file 'tests/unit-tests/test_data/libamd64.so'
751Binary files tests/unit-tests/test_data/libamd64.so 1970-01-01 00:00:00 +0000 and tests/unit-tests/test_data/libamd64.so 2014-09-08 04:22:15 +0000 differ
752=== added file 'tests/unit-tests/test_data/libarmhf.so'
753Binary files tests/unit-tests/test_data/libarmhf.so 1970-01-01 00:00:00 +0000 and tests/unit-tests/test_data/libarmhf.so 2014-09-08 04:22:15 +0000 differ
754=== added file 'tests/unit-tests/test_shared_library_prober.cpp'
755--- tests/unit-tests/test_shared_library_prober.cpp 1970-01-01 00:00:00 +0000
756+++ tests/unit-tests/test_shared_library_prober.cpp 2014-09-08 04:22:15 +0000
757@@ -0,0 +1,182 @@
758+/*
759+ * Copyright © 2014 Canonical Ltd.
760+ *
761+ * This program is free software: you can redistribute it and/or modify it
762+ * under the terms of the GNU General Public License version 3,
763+ * as published by the Free Software Foundation.
764+ *
765+ * This program is distributed in the hope that it will be useful,
766+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
767+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
768+ * GNU General Public License for more details.
769+ *
770+ * You should have received a copy of the GNU General Public License
771+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
772+ *
773+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
774+ */
775+
776+#include "mir/shared_library_prober.h"
777+
778+#include "mir_test_framework/executable_path.h"
779+
780+#include <stdlib.h>
781+#include <errno.h>
782+#include <unistd.h>
783+#include <cstring>
784+
785+#include <system_error>
786+#include <gtest/gtest.h>
787+#include <gmock/gmock.h>
788+
789+namespace mtf = mir_test_framework;
790+
791+namespace
792+{
793+class MockSharedLibraryProberReport : public mir::SharedLibraryProberReport
794+{
795+public:
796+ MOCK_METHOD1(probing_path, void(boost::filesystem::path const&));
797+ MOCK_METHOD2(probing_failed, void(boost::filesystem::path const&, std::exception const&));
798+ MOCK_METHOD1(loading_library, void(boost::filesystem::path const&));
799+ MOCK_METHOD2(loading_failed, void(boost::filesystem::path const&, std::exception const&));
800+};
801+
802+class SharedLibraryProber : public testing::Test
803+{
804+public:
805+ SharedLibraryProber()
806+ : library_path{mtf::executable_path() + "/test_data"}
807+ {
808+ // Can't use std::string, as mkdtemp mutates its argument.
809+ auto tmp_name = std::unique_ptr<char[], std::function<void(char*)>>{strdup("/tmp/mir_empty_directory_XXXXXX"),
810+ [](char* data) {free(data);}};
811+ if (mkdtemp(tmp_name.get()) == NULL)
812+ {
813+ throw std::system_error{errno, std::system_category(), "Failed to create temporary directory"};
814+ }
815+ temporary_directory = std::string{tmp_name.get()};
816+ }
817+
818+ ~SharedLibraryProber()
819+ {
820+ // Can't do anything useful in case of failure...
821+ rmdir(temporary_directory.c_str());
822+ }
823+
824+ std::string const library_path;
825+ std::string temporary_directory;
826+ testing::NiceMock<MockSharedLibraryProberReport> null_report;
827+};
828+
829+}
830+
831+TEST_F(SharedLibraryProber, ReturnsNonEmptyListForPathContainingLibraries)
832+{
833+ auto libraries = mir::libraries_for_path(library_path, null_report);
834+ EXPECT_GE(libraries.size(), 1);
835+}
836+
837+TEST_F(SharedLibraryProber, RaisesExceptionForNonexistentPath)
838+{
839+ EXPECT_THROW(mir::libraries_for_path("/a/path/that/certainly/doesnt/exist", null_report),
840+ std::system_error);
841+}
842+
843+TEST_F(SharedLibraryProber, NonExistentPathRaisesENOENTError)
844+{
845+ try
846+ {
847+ mir::libraries_for_path("/a/path/that/certainly/doesnt/exist", null_report);
848+ }
849+ catch (std::system_error &err)
850+ {
851+ EXPECT_EQ(err.code(), std::error_code(ENOENT, std::system_category()));
852+ }
853+}
854+
855+TEST_F(SharedLibraryProber, PathWithNoSharedLibrariesReturnsEmptyList)
856+{
857+ auto libraries = mir::libraries_for_path(temporary_directory.c_str(), null_report);
858+ EXPECT_EQ(0, libraries.size());
859+}
860+
861+TEST_F(SharedLibraryProber, LogsStartOfProbe)
862+{
863+ using namespace testing;
864+ testing::NiceMock<MockSharedLibraryProberReport> report;
865+
866+ EXPECT_CALL(report, probing_path(testing::Eq(library_path)));
867+
868+ mir::libraries_for_path(library_path, report);
869+}
870+
871+TEST_F(SharedLibraryProber, LogsForNonexistentPath)
872+{
873+ using namespace testing;
874+ NiceMock<MockSharedLibraryProberReport> report;
875+
876+ EXPECT_CALL(report, probing_path(testing::Eq("/yo/dawg/I/heard/you/liked/slashes")));
877+
878+ EXPECT_THROW(mir::libraries_for_path("/yo/dawg/I/heard/you/liked/slashes", report),
879+ std::runtime_error);
880+}
881+
882+TEST_F(SharedLibraryProber, LogsFailureForNonexistentPath)
883+{
884+ using namespace testing;
885+ NiceMock<MockSharedLibraryProberReport> report;
886+
887+ EXPECT_CALL(report, probing_failed(Eq("/yo/dawg/I/heard/you/liked/slashes"), _));
888+
889+ EXPECT_THROW(mir::libraries_for_path("/yo/dawg/I/heard/you/liked/slashes", report),
890+ std::runtime_error);
891+
892+}
893+
894+TEST_F(SharedLibraryProber, LogsNoLibrariesForPathWithoutLibraries)
895+{
896+ using namespace testing;
897+ NiceMock<MockSharedLibraryProberReport> report;
898+
899+ EXPECT_CALL(report, loading_library(_)).Times(0);
900+
901+ mir::libraries_for_path(temporary_directory.c_str(), report);
902+}
903+
904+namespace
905+{
906+MATCHER_P(FilenameMatches, path, "")
907+{
908+ *result_listener << "where the path is " << arg;
909+ return boost::filesystem::path(path).filename() == arg.filename();
910+}
911+}
912+
913+TEST_F(SharedLibraryProber, LogsEachLibraryProbed)
914+{
915+ using namespace testing;
916+ NiceMock<MockSharedLibraryProberReport> report;
917+
918+ EXPECT_CALL(report, loading_library(FilenameMatches("libamd64.so")));
919+ EXPECT_CALL(report, loading_library(FilenameMatches("libarmhf.so")));
920+
921+ mir::libraries_for_path(library_path, report);
922+}
923+
924+TEST_F(SharedLibraryProber, LogsFailureForLoadFailure)
925+{
926+ using namespace testing;
927+ NiceMock<MockSharedLibraryProberReport> report;
928+
929+ bool armhf_failed{false}, amd64_failed{false};
930+
931+ ON_CALL(report, loading_failed(FilenameMatches("libamd64.so"), _))
932+ .WillByDefault(InvokeWithoutArgs([&amd64_failed]() { amd64_failed = true; }));
933+ ON_CALL(report, loading_failed(FilenameMatches("libarmhf.so"), _))
934+ .WillByDefault(InvokeWithoutArgs([&armhf_failed]() { armhf_failed = true; }));
935+
936+ mir::libraries_for_path(library_path, report);
937+
938+ EXPECT_TRUE(amd64_failed || armhf_failed);
939+}

Subscribers

People subscribed via source and target branches