Mir

Merge lp:~alan-griffiths/mir/fix-1488500 into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 2887
Proposed branch: lp:~alan-griffiths/mir/fix-1488500
Merge into: lp:mir
Diff against target: 80 lines (+39/-15)
1 file modified
src/common/sharedlibrary/shared_library_prober.cpp (+39/-15)
To merge this branch: bzr merge lp:~alan-griffiths/mir/fix-1488500
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Approve
Alexandros Frantzis (community) Approve
Review via email: mp+269171@code.launchpad.net

Commit message

Try the newest versions of client graphics platform module ".so"s first.
(LP: #1488500)

Description of the change

Try the newest versions of client graphics platform module ".so"s first.

As well as being efficient, this is because if we attempt to load functions from mesa.so.2 before those from mesa.so.3 we get a segfault.

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

I think newest first is still overcomplicated and makes the system unreliable because the fallback to older ABIs likely will break, even crash. When we break ABIs we don't imply any compatibility between them. We should be trying newest only, instead of newest first...

Given that:
   set(MIR_CLIENT_PLATFORM_ABI 3)

Mir should only try to load:
   lib/client-modules/*.so.3

Or it should load * and be able to query the ABI level internally. Only accepting a perfect match for MIR_CLIENT_PLATFORM_ABI == 3.

A better file naming scheme would also help, but that can come later.

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

> As well as being efficient, this is because if we attempt to load functions from
> mesa.so.2 before those from mesa.so.3 we get a segfault.

Why does this happen? Is there a way to fix this at its core, instead of working around it?

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

Daniel:
We load versioned symbols, so loading from a driver that doesn't support the correct version fails and we don't ever call incompatible code. This isn't about ABI breaks, it is about something odd that our mesa driver does (see response to Alexandros below for my current guess).

Enforcing that the library is numbered for the ABI version would prevent a driver module exporting symbols for multiple versions. We don't do that currently but it could conceivably be a useful hack.

Alexandros:
You're right, I haven't root caused this yet. But the MP avoids an embarrassing problem while reducing the chance that we try to load symbols from an obsolete module.

I suspect the problem is caused by the ensure_loaded_with_rtld_global_mesa_client() hack used to force mir_client_mesa_egl_native_display_is_valid into the global symbol table having unintended side effects.

It is too late to fix that in mesa.so.2 even if I knew how.

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

Two issues/questions:

Do we know if the older to newer load order important for this bug to occur, or could it be caused by just loading two mesa modules in the future regardless of order?

If it's the latter, then the proposed solution is problematic, since in the future a server that needs to use an older mesa platform will run into the same segfault (e.g., server needs 4, loads mesa.so.5 first, then mesa.so.4).

30 + return atoi(++lhbuf) > atoi(++rhbuf);

Better to use strtol() that's guaranteed to have well defined behavior for all inputs strings.

Needs info/fixing

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

Yes, I would expect there to be a problem with a server that wanted the older mesa module.

But, while we release updates to all downstream servers with each Mir release, that is less bad than the current situation.

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

OK as a quick (and temporary?) workaround, as long as we are aware that we will probably come across this problem again in some form (e.g. using an older server/platform installed in parallel with newer ones) in the future.

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

Alright, if it works...

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) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common/sharedlibrary/shared_library_prober.cpp'
2--- src/common/sharedlibrary/shared_library_prober.cpp 2015-07-16 07:03:19 +0000
3+++ src/common/sharedlibrary/shared_library_prober.cpp 2015-08-27 11:27:36 +0000
4@@ -19,8 +19,10 @@
5 #include "mir/shared_library_prober.h"
6 #include "mir/shared_library.h"
7
8+#include <boost/filesystem.hpp>
9+
10 #include <system_error>
11-#include <boost/filesystem.hpp>
12+#include <cstring>
13
14 namespace
15 {
16@@ -47,6 +49,20 @@
17
18 }
19
20+namespace
21+{
22+bool greater_soname_version(boost::filesystem::path const& lhs, boost::filesystem::path const& rhs)
23+{
24+ auto lhbuf = strrchr(lhs.c_str(), '.');
25+ auto rhbuf = strrchr(rhs.c_str(), '.');
26+
27+ if (!rhbuf) return lhbuf;
28+ if (!lhbuf) return false;
29+
30+ return strtol(++lhbuf, 0, 0) > strtol(++rhbuf, 0, 0);
31+}
32+}
33+
34 std::vector<std::shared_ptr<mir::SharedLibrary>>
35 mir::libraries_for_path(std::string const& path, mir::SharedLibraryProberReport& report)
36 {
37@@ -62,21 +78,29 @@
38 throw error;
39 }
40
41- std::vector<std::shared_ptr<mir::SharedLibrary>> libraries;
42+ std::vector<boost::filesystem::path> libraries;
43 for (; iterator != boost::filesystem::directory_iterator() ; ++iterator)
44 {
45 if (path_has_library_extension(iterator->path()))
46- {
47- try
48- {
49- report.loading_library(iterator->path());
50- libraries.emplace_back(std::make_shared<mir::SharedLibrary>(iterator->path().string()));
51- }
52- catch (std::runtime_error const& err)
53- {
54- report.loading_failed(iterator->path(), err);
55- }
56- }
57- }
58- return libraries;
59+ libraries.push_back(iterator->path().string());
60+ }
61+
62+ std::sort(libraries.begin(), libraries.end(), &greater_soname_version);
63+
64+ std::vector<std::shared_ptr<mir::SharedLibrary>> result;
65+
66+ for(auto& lib : libraries)
67+ {
68+ try
69+ {
70+ report.loading_library(lib);
71+ result.emplace_back(std::make_shared<mir::SharedLibrary>(lib.string()));
72+ }
73+ catch (std::runtime_error const& err)
74+ {
75+ report.loading_failed(lib, err);
76+ }
77+ }
78+
79+ return result;
80 }

Subscribers

People subscribed via source and target branches