Merge lp:~alan-griffiths/mir/fix-1543049 into lp:mir
- fix-1543049
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3363 |
Proposed branch: | lp:~alan-griffiths/mir/fix-1543049 |
Merge into: | lp:mir |
Diff against target: |
140 lines (+54/-36) 3 files modified
src/server/input/input_probe.cpp (+35/-36) tests/unit-tests/CMakeLists.txt (+1/-0) tests/unit-tests/input/test_input_platform_probing.cpp (+18/-0) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/fix-1543049 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Chris Halse Rogers | Approve | ||
Daniel van Vugt | Abstain | ||
Andreas Pokorny (community) | Approve | ||
Cemil Azizoglu (community) | Approve | ||
Review via email: mp+287644@code.launchpad.net |
Commit message
input: update mi::probe_
Description of the change
input: update mi::probe_
Alan Griffiths (alan-griffiths) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3354
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Ok.
Nit : s/huristic/
62 + // This is a huristic that assumes we're always looking for the most up-to-date driver,
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3355
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
yeah just played the scenario of bumping one ABI.. this works.
Chris Halse Rogers (raof) wrote : | # |
Oooh! You know what we should do? We should *first* dlopen(NULL, $STUFF) and see if we can resolve the relevant symbols from there!
If we can, then that means we've already loaded a module that provides the symbol, and we should use it. That'd resolve:
+ // TODO find a way to coordinate the selection of mesa-x11 and input platforms
Does that work to fix the bug?
Chris Halse Rogers (raof) wrote : | # |
(That'd be mir::SharedLibrary us{nullptr};)
Alan Griffiths (alan-griffiths) wrote : | # |
On Tuesday, 1 March 2016 23:13:53 GMT, Chris Halse Rogers
<email address hidden> wrote:
> Review: Needs Information
>
> Oooh! You know what we should do? We should *first*
> dlopen(NULL, $STUFF) and see if we can resolve the relevant
> symbols from there!
>
> If we can, then that means we've already loaded a module that
> provides the symbol, and we should use it. That'd resolve:
> + // TODO find a way to coordinate the selection
> of mesa-x11 and input platforms
>
> Does that work to fix the bug?
Seems somewhat orthogonal to the bug, and only addresses the comment if
both the graphics module is guaranteed to load first and we only want one
input module. (We return a collection for some reason.)
--
Alan Griffiths. +44 (0)798 9938 758
Octopull Limited. http://
Chris Halse Rogers (raof) wrote : | # |
My understanding of the bug is that we have a problem when we load mesa-x11 as the graphics module and then load a *different* mesa-x11 as the input module. Is that not correct?
Having both the input probe and graphics probe first check if the relevant symbol is already by an already-loaded module would fix this.
(Sorry for the direct mail, there. Stupid not-reply-all).
Daniel van Vugt (vanvugt) wrote : | # |
Although it's clearly possible to set up a machine to make the test case in question fail, most peoples' machines are not failing any tests even while the bug exists. So can we add a new unit test for the issue to cover that gap?
Alan Griffiths (alan-griffiths) wrote : | # |
> Although it's clearly possible to set up a machine to make the test case in
> question fail, most peoples' machines are not failing any tests even while the
> bug exists.
All you need is a working copy in which you've built Mir. Then, as indicated in the bug, bump MIR_SERVER_
This can happen in normal workflow either when you, or a branch you merge updates the graphics platform ABI. As noted in the bug deleting the old lib works around the problem.
AFAIK we've never yet replicated this problem with a release, but as Chris indicates, it could also impact some upgrade scenarios.
> So can we add a new unit test for the issue to cover that gap?
Hmm. Because the logic is hard coded to the real filesystem there's no convenient "seam" for testing, but I'll have a think about the best way to address this.
Alan Griffiths (alan-griffiths) wrote : | # |
> My understanding of the bug is that we have a problem when we load mesa-x11 as
> the graphics module and then load a *different* mesa-x11 as the input module.
> Is that not correct?
Strictly, that's not the scenario described in the linked bug. The bug is that we try to load multiple mesa-x11 input modules.
What you describe is indeed a potential issue as mentioned in the TODO comment.
> Having both the input probe and graphics probe first check if the relevant
> symbol is already by an already-loaded module would fix this.
For reasons I don't yet understand the input probing can (and does) select multiple input modules. The logic to match already-loaded modules so as to reject related candidates but not reject unrelated candidates is not as simple as just looking for a symbol. I'd rather leave that for a future MP (hence the TODO).
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3357
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
> For reasons I don't yet understand the input probing can (and does) select
> multiple input modules. The logic to match already-loaded modules so as to
> reject related candidates but not reject unrelated candidates is not as simple
> as just looking for a symbol. I'd rather leave that for a future MP (hence the
> TODO).
I've discussed this with Andreas and we don't need multiple input modules.
I'd like to land and build on this MP. Two changes will follow: refactoring to using a single input module; and then, as you suggest, checking to see if we've already loaded a satisfactory module.
Andreas Pokorny (andreas-pokorny) wrote : | # |
Yeah I agree to the plan..
Alan Griffiths (alan-griffiths) wrote : | # |
> Oooh! You know what we should do? We should *first* dlopen(NULL, $STUFF) and
> see if we can resolve the relevant symbols from there!
One of us is missing something. Surely that can't work modules (correctly) loaded with RTLD_LOCAL?
Daniel van Vugt (vanvugt) wrote : | # |
I understand the "seam" problem. I'm dealing with a similar one myself...
P.S. The single input module approach is probably going to bite us:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
> I'm unsure whether I should add the following to the selection logic around
> line 60
>
> // Ignore modules from different major versions of Mir
> if (MIR_VERSION_MAJOR != desc->major_
> return Selection::persist;
>
> // Ignore modules from more recent minor versions of Mir
> if (MIR_VERSION_MINOR < desc->minor_
> return Selection::persist;
>
> Does anyone have an opinion either way?
Answering my own question - that only works for plugins we supply ourselves (with MIR_VERSION based versioning).
Alan Griffiths (alan-griffiths) wrote : | # |
> Oooh! You know what we should do? We should *first* dlopen(NULL, $STUFF) and
> see if we can resolve the relevant symbols from there!
>
> If we can, then that means we've already loaded a module that provides the
> symbol, and we should use it. That'd resolve:
> + // TODO find a way to coordinate the selection of mesa-x11
> and input platforms
Give or take the detail that dlopen(NULL, $STUFF) won't work (modules are loaded with RTLD_LOCAL) and different trick is needed that's the approach taken in a grandchild of this MP:
lp:~alan-griffiths/mir/spike-input-from-the-existing-graphics-module/+merge/287964
So you're probably happy with this part of it now?
Chris Halse Rogers (raof) wrote : | # |
Yup, I'm happy with this now.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Mir CI Bot (mir-ci-bot) : | # |
Preview Diff
1 | === modified file 'src/server/input/input_probe.cpp' |
2 | --- src/server/input/input_probe.cpp 2015-10-14 15:22:39 +0000 |
3 | +++ src/server/input/input_probe.cpp 2016-03-02 10:44:16 +0000 |
4 | @@ -34,22 +34,6 @@ |
5 | |
6 | namespace |
7 | { |
8 | -auto probe_input_platform(mir::SharedLibrary const& lib, mir::options::Option const& options) |
9 | -{ |
10 | - auto probe = lib.load_function<mi::ProbePlatform>("probe_input_platform", MIR_SERVER_INPUT_PLATFORM_VERSION); |
11 | - |
12 | - return probe(options); |
13 | -} |
14 | - |
15 | -void describe_input_platform(mir::SharedLibrary const& lib) |
16 | -{ |
17 | - auto describe = |
18 | - lib.load_function<mi::DescribeModule>("describe_input_module", MIR_SERVER_INPUT_PLATFORM_VERSION); |
19 | - auto desc = describe(); |
20 | - mir::log_info("Selected input driver: %s (version: %d.%d.%d)", desc->name, desc->major_version, desc->minor_version, |
21 | - desc->micro_version); |
22 | -} |
23 | - |
24 | mir::UniqueModulePtr<mi::Platform> create_input_platform( |
25 | mir::SharedLibrary const& lib, mir::options::Option const& options, |
26 | std::shared_ptr<mir::EmergencyCleanupRegistry> const& cleanup_registry, |
27 | @@ -67,37 +51,52 @@ |
28 | std::shared_ptr<mi::InputDeviceRegistry> const& device_registry, std::shared_ptr<mi::InputReport> const& input_report, |
29 | mir::SharedLibraryProberReport& prober_report) |
30 | { |
31 | + auto reject_platform_priority = mi::PlatformPriority::dummy; |
32 | + |
33 | std::vector<UniqueModulePtr<Platform>> platforms; |
34 | - |
35 | - if (options.is_set(mo::platform_input_lib)) |
36 | - { |
37 | - mir::SharedLibrary lib(options.get<std::string>(mo::platform_input_lib)); |
38 | - |
39 | - platforms.emplace_back(create_input_platform(lib, options, emergency_cleanup, device_registry, input_report)); |
40 | - |
41 | - describe_input_platform(lib); |
42 | - } |
43 | - else |
44 | - { |
45 | - auto const& path = options.get<std::string>(mo::platform_path); |
46 | - auto platforms_libs = mir::libraries_for_path(path, prober_report); |
47 | - |
48 | - for (auto const& platform_lib : platforms_libs) |
49 | + std::vector<std::string> module_names; |
50 | + |
51 | + auto const module_selector = [&](std::shared_ptr<mir::SharedLibrary> const& module) |
52 | { |
53 | try |
54 | { |
55 | - if (probe_input_platform(*platform_lib, options) > mi::PlatformPriority::dummy) |
56 | + auto const probe = module->load_function<mi::ProbePlatform>( |
57 | + "probe_input_platform", MIR_SERVER_INPUT_PLATFORM_VERSION); |
58 | + auto const desc = module->load_function<mi::DescribeModule>( |
59 | + "describe_input_module", MIR_SERVER_INPUT_PLATFORM_VERSION)(); |
60 | + |
61 | + // We only take the first found of duplicate modules, as that will be the most recent. |
62 | + // This is a heuristic that assumes we're always looking for the most up-to-date driver, |
63 | + // TODO find a way to coordinate the selection of mesa-x11 and input platforms |
64 | + auto const duplicate = find(begin(module_names), end(module_names), desc->name) != end(module_names); |
65 | + |
66 | + if (probe(options) > reject_platform_priority && !duplicate) |
67 | { |
68 | platforms.emplace_back( |
69 | - create_input_platform(*platform_lib, options, emergency_cleanup, device_registry, input_report)); |
70 | - |
71 | - describe_input_platform(*platform_lib); |
72 | + create_input_platform(*module, options, emergency_cleanup, device_registry, input_report)); |
73 | + |
74 | + module_names.push_back(desc->name); |
75 | + |
76 | + mir::log_info("Selected input driver: %s (version: %d.%d.%d)", |
77 | + desc->name, desc->major_version, desc->minor_version, desc->micro_version); |
78 | } |
79 | } |
80 | catch (std::runtime_error const&) |
81 | { |
82 | + // Assume we were handed a SharedLibrary that's not an input module of the correct vintage. |
83 | } |
84 | - } |
85 | + |
86 | + return Selection::persist; |
87 | + }; |
88 | + |
89 | + if (options.is_set(mo::platform_input_lib)) |
90 | + { |
91 | + reject_platform_priority = PlatformPriority::unsupported; |
92 | + module_selector(std::make_shared<mir::SharedLibrary>(options.get<std::string>(mo::platform_input_lib))); |
93 | + } |
94 | + else |
95 | + { |
96 | + select_libraries_for_path(options.get<std::string>(mo::platform_path), module_selector, prober_report); |
97 | } |
98 | |
99 | return platforms; |
100 | |
101 | === modified file 'tests/unit-tests/CMakeLists.txt' |
102 | --- tests/unit-tests/CMakeLists.txt 2016-02-24 03:55:11 +0000 |
103 | +++ tests/unit-tests/CMakeLists.txt 2016-03-02 10:44:16 +0000 |
104 | @@ -2,6 +2,7 @@ |
105 | |
106 | add_definitions( |
107 | -DMIR_CLIENT_PLATFORM_VERSION="${MIR_CLIENT_PLATFORM_VERSION}" |
108 | + -DMIR_SERVER_GRAPHICS_PLATFORM_ABI_STRING="${MIR_SERVER_GRAPHICS_PLATFORM_ABI}" |
109 | ) |
110 | |
111 | if (MIR_BUILD_PLATFORM_ANDROID) |
112 | |
113 | === modified file 'tests/unit-tests/input/test_input_platform_probing.cpp' |
114 | --- tests/unit-tests/input/test_input_platform_probing.cpp 2015-12-02 13:22:51 +0000 |
115 | +++ tests/unit-tests/input/test_input_platform_probing.cpp 2016-03-02 10:44:16 +0000 |
116 | @@ -149,6 +149,24 @@ |
117 | EXPECT_THAT(platforms, UnorderedElementsAre(OfPtrType<mi::evdev::Platform>(), OfPtrType<mi::X::XInputPlatform>())); |
118 | } |
119 | |
120 | +TEST_F(InputPlatformProbe, when_multiple_x11_platforms_are_eligible_only_one_is_selected) |
121 | +{ |
122 | + auto const real_lib = mtf::server_platform_path() + "server-mesa-x11.so." MIR_SERVER_GRAPHICS_PLATFORM_ABI_STRING; |
123 | + auto const fake_lib = mtf::server_platform_path() + "server-mesa-x11.so.0"; |
124 | + |
125 | + ASSERT_THAT(real_lib, Ne(fake_lib)); |
126 | + remove(fake_lib.c_str()); |
127 | + ASSERT_THAT(link(real_lib.c_str(), fake_lib.c_str()), Eq(0)); |
128 | + |
129 | + auto platforms = |
130 | + mi::probe_input_platforms(mock_options, mt::fake_shared(stub_emergency), mt::fake_shared(mock_registry), |
131 | + mr::null_input_report(), *stub_prober_report); |
132 | + |
133 | + EXPECT_THAT(platforms, UnorderedElementsAre(OfPtrType<mi::evdev::Platform>(), OfPtrType<mi::X::XInputPlatform>())); |
134 | + |
135 | + remove(fake_lib.c_str()); |
136 | +} |
137 | + |
138 | TEST_F(InputPlatformProbe, x11_input_platform_not_used_when_vt_specified) |
139 | { |
140 | ON_CALL(mock_options, is_set(StrEq(vt))).WillByDefault(Return(true)); |
I'm unsure whether I should add the following to the selection logic around line 60
// Ignore modules from different major versions of Mir version)
return Selection::persist;
if (MIR_VERSION_MAJOR != desc->major_
// Ignore modules from more recent minor versions of Mir version)
return Selection::persist;
if (MIR_VERSION_MINOR < desc->minor_
Does anyone have an opinion either way?