Skip to content

Commit 4a5defa

Browse files
committed
asan: changing how stub input platform is allocated to avoid statics leaking into libraries that include it
1 parent a6a4041 commit 4a5defa

8 files changed

+204
-69
lines changed

tests/include/mir_test_framework/stub_input_platform.h

+17-8
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,22 @@ class InputDevice;
3636
}
3737
namespace mir_test_framework
3838
{
39+
40+
class DeviceStore
41+
{
42+
public:
43+
virtual ~DeviceStore() = default;
44+
virtual void foreach_device(std::function<void(std::weak_ptr<mir::input::InputDevice> const&)> const&) = 0;
45+
virtual void clear() = 0;
46+
};
47+
3948
class FakeInputDevice;
4049
class StubInputPlatform : public mir::input::Platform
4150
{
4251
public:
43-
explicit StubInputPlatform(std::shared_ptr<mir::input::InputDeviceRegistry> const& input_device_registry);
52+
explicit StubInputPlatform(
53+
std::shared_ptr<mir::input::InputDeviceRegistry> const& input_device_registry,
54+
std::shared_ptr<DeviceStore> const& device_store);
4455
~StubInputPlatform();
4556

4657
std::shared_ptr<mir::dispatch::Dispatchable> dispatchable() override;
@@ -49,18 +60,16 @@ class StubInputPlatform : public mir::input::Platform
4960
void pause_for_config() override;
5061
void continue_after_config() override;
5162

52-
static void add(std::shared_ptr<mir::input::InputDevice> const& dev);
53-
static void remove(std::shared_ptr<mir::input::InputDevice> const& dev);
54-
static void register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
55-
static void unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
63+
void add(std::shared_ptr<mir::input::InputDevice> const& dev);
64+
void remove(std::shared_ptr<mir::input::InputDevice> const& dev);
65+
void register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
66+
void unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
5667

5768
private:
5869
std::shared_ptr<mir::dispatch::MultiplexingDispatchable> const platform_dispatchable;
5970
std::shared_ptr<mir::dispatch::ActionQueue> const platform_queue;
6071
std::shared_ptr<mir::input::InputDeviceRegistry> const registry;
61-
static std::atomic<StubInputPlatform*> stub_input_platform;
62-
static std::vector<std::weak_ptr<mir::input::InputDevice>> device_store;
63-
static std::mutex device_store_guard;
72+
std::shared_ptr<DeviceStore> const device_store;
6473
};
6574

6675
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright © Canonical Ltd.
3+
*
4+
* This program is free software: you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 or 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#ifndef MIR_TEST_FRAMEWORK_STUB_INPUT_PLATFORM_ACCESSOR_H
18+
#define MIR_TEST_FRAMEWORK_STUB_INPUT_PLATFORM_ACCESSOR_H
19+
20+
#include "stub_input_platform.h"
21+
22+
namespace mir_test_framework
23+
{
24+
class StubInputPlatformAccessor
25+
{
26+
public:
27+
static mir::UniqueModulePtr<mir::input::Platform> get(std::shared_ptr<mir::input::InputDeviceRegistry> const& input_device_registry);
28+
static void add(std::shared_ptr<mir::input::InputDevice> const& dev);
29+
static void remove(std::shared_ptr<mir::input::InputDevice> const& dev);
30+
static void register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
31+
static void unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue);
32+
static void clear();
33+
34+
private:
35+
static std::atomic<StubInputPlatform*> stub_input_platform;
36+
37+
};
38+
}
39+
40+
#endif //MIR_TEST_FRAMEWORK_STUB_INPUT_PLATFORM_ACCESSOR_H

tests/mir_test_framework/CMakeLists.txt

+15-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ add_compile_definitions(
2121
string (REPLACE " -flto " " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
2222
string (REPLACE " -flto " " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
2323

24+
add_library(mir-stub-input-platform OBJECT
25+
stub_input_platform.cpp
26+
)
27+
28+
target_link_libraries(mir-stub-input-platform
29+
PUBLIC
30+
mirplatform
31+
mircommon
32+
mircore
33+
)
34+
2435
add_library(mir-public-test-framework OBJECT
2536
async_server_runner.cpp
2637
command_line_server_configuration.cpp
@@ -93,6 +104,7 @@ target_link_libraries(mir-umock-test-framework
93104

94105
add_library(mir-test-framework-static STATIC
95106
$<TARGET_OBJECTS:mir-public-test-framework>
107+
$<TARGET_OBJECTS:mir-stub-input-platform>
96108
$<TARGET_OBJECTS:mir-protected-test-framework>
97109
$<TARGET_OBJECTS:mir-public-test>
98110
)
@@ -115,8 +127,8 @@ add_library(
115127
mir-test-input-framework OBJECT
116128

117129
stub_input.cpp
130+
stub_input_platform_accessor.cpp
118131
fake_input_device_impl.cpp
119-
stub_input_platform.cpp
120132
)
121133

122134
target_link_libraries(mir-test-input-framework
@@ -129,7 +141,8 @@ target_link_libraries(mir-test-input-framework
129141
add_library(
130142
mirplatforminputstub MODULE
131143
$<TARGET_OBJECTS:mir-test-input-framework>
132-
$<TARGET_OBJECTS:mirevdevutilsobjects>)
144+
$<TARGET_OBJECTS:mirevdevutilsobjects>
145+
$<TARGET_OBJECTS:mir-stub-input-platform>)
133146
target_link_libraries(mirplatforminputstub mircommon)
134147

135148
set_target_properties(

tests/mir_test_framework/fake_input_device_impl.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "fake_input_device_impl.h"
18-
#include "mir_test_framework/stub_input_platform.h"
18+
#include "mir_test_framework/stub_input_platform_accessor.h"
1919

2020
#include "mir/input/input_device.h"
2121
#include "mir/input/input_device_info.h"
@@ -45,12 +45,12 @@ namespace synthesis = mir::input::synthesis;
4545
mtf::FakeInputDeviceImpl::FakeInputDeviceImpl(mi::InputDeviceInfo const& info)
4646
: queue{std::make_shared<md::ActionQueue>()}, device{std::make_shared<InputDevice>(info, queue)}
4747
{
48-
mtf::StubInputPlatform::add(device);
48+
mtf::StubInputPlatformAccessor::add(device);
4949
}
5050

5151
void mtf::FakeInputDeviceImpl::emit_device_removal()
5252
{
53-
mtf::StubInputPlatform::remove(device);
53+
mtf::StubInputPlatformAccessor::remove(device);
5454
}
5555

5656
void mtf::FakeInputDeviceImpl::emit_runtime_error()
@@ -328,14 +328,14 @@ void mtf::FakeInputDeviceImpl::InputDevice::start(mi::InputSink* destination, mi
328328
{
329329
sink = destination;
330330
builder = event_builder;
331-
mtf::StubInputPlatform::register_dispatchable(queue);
331+
mtf::StubInputPlatformAccessor::register_dispatchable(queue);
332332
}
333333

334334
void mtf::FakeInputDeviceImpl::InputDevice::stop()
335335
{
336336
sink = nullptr;
337337
builder = nullptr;
338-
mtf::StubInputPlatform::unregister_dispatchable(queue);
338+
mtf::StubInputPlatformAccessor::unregister_dispatchable(queue);
339339
}
340340

341341
mi::OutputInfo mtf::FakeInputDeviceImpl::InputDevice::get_output_info() const

tests/mir_test_framework/stub_input.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
*/
1616

17-
#include "mir_test_framework/stub_input_platform.h"
17+
#include "mir_test_framework/stub_input_platform_accessor.h"
1818
#include "fake_input_device_impl.h"
1919
#include "mir/module_properties.h"
2020
#include "mir/assert_module_entry_point.h"
@@ -33,7 +33,7 @@ mir::UniqueModulePtr<mi::Platform> create_input_platform(
3333
std::shared_ptr<mi::InputReport> const& /*report*/)
3434
{
3535
mir::assert_entry_point_signature<mi::CreatePlatform>(&create_input_platform);
36-
return mir::make_module_ptr<mtf::StubInputPlatform>(input_device_registry);
36+
return mtf::StubInputPlatformAccessor::get(input_device_registry);
3737
}
3838

3939
void add_input_platform_options(

tests/mir_test_framework/stub_input_platform.cpp

+15-51
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,29 @@ namespace mtf = mir_test_framework;
2727
namespace mi = mir::input;
2828

2929
mtf::StubInputPlatform::StubInputPlatform(
30-
std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry)
30+
std::shared_ptr<mi::InputDeviceRegistry> const& input_device_registry,
31+
std::shared_ptr<DeviceStore> const& device_store)
3132
: platform_dispatchable{std::make_shared<mir::dispatch::MultiplexingDispatchable>()},
3233
platform_queue{std::make_shared<mir::dispatch::ActionQueue>()},
33-
registry(input_device_registry)
34+
registry(input_device_registry),
35+
device_store(device_store)
3436
{
35-
stub_input_platform = this;
3637
platform_dispatchable->add_watch(platform_queue);
3738
}
3839

3940
mtf::StubInputPlatform::~StubInputPlatform()
4041
{
41-
std::lock_guard lk{device_store_guard};
42-
device_store.clear();
43-
stub_input_platform = nullptr;
42+
device_store->clear();
4443
}
4544

4645
void mtf::StubInputPlatform::start()
4746
{
48-
std::lock_guard lk{device_store_guard};
49-
for (auto const& dev : device_store)
47+
device_store->foreach_device([&](auto const& dev)
5048
{
5149
auto device = dev.lock();
5250
if (device)
5351
registry->add_device(device);
54-
}
52+
});
5553
}
5654

5755
std::shared_ptr<mir::dispatch::Dispatchable> mtf::StubInputPlatform::dispatchable()
@@ -61,13 +59,12 @@ std::shared_ptr<mir::dispatch::Dispatchable> mtf::StubInputPlatform::dispatchabl
6159

6260
void mtf::StubInputPlatform::stop()
6361
{
64-
std::lock_guard lk{device_store_guard};
65-
for (auto const& dev : device_store)
62+
device_store->foreach_device([&](auto const& dev)
6663
{
6764
auto device = dev.lock();
6865
if (device)
6966
registry->remove_device(device);
70-
}
67+
});
7168
}
7269

7370
void mtf::StubInputPlatform::pause_for_config()
@@ -80,61 +77,28 @@ void mtf::StubInputPlatform::continue_after_config()
8077

8178
void mtf::StubInputPlatform::add(std::shared_ptr<mir::input::InputDevice> const& dev)
8279
{
83-
auto input_platform = stub_input_platform.load();
84-
if (!input_platform)
85-
{
86-
std::lock_guard lk{device_store_guard};
87-
device_store.push_back(dev);
88-
return;
89-
}
90-
91-
input_platform->platform_queue->enqueue(
92-
[registry=input_platform->registry,dev]
80+
platform_queue->enqueue(
81+
[registry=registry,dev]
9382
{
9483
registry->add_device(dev);
9584
});
9685
}
9786

9887
void mtf::StubInputPlatform::remove(std::shared_ptr<mir::input::InputDevice> const& dev)
9988
{
100-
auto input_platform = stub_input_platform.load();
101-
if (!input_platform)
102-
BOOST_THROW_EXCEPTION(std::runtime_error("No stub input platform available"));
103-
104-
std::lock_guard lk{device_store_guard};
105-
device_store.erase(
106-
std::remove_if(begin(device_store),
107-
end(device_store),
108-
[dev](auto weak_dev)
109-
{
110-
return (weak_dev.lock() == dev);
111-
}),
112-
end(device_store));
113-
input_platform->platform_queue->enqueue(
114-
[ registry = input_platform->registry, dev ]
89+
platform_queue->enqueue(
90+
[ registry = registry, dev ]
11591
{
11692
registry->remove_device(dev);
11793
});
11894
}
11995

12096
void mtf::StubInputPlatform::register_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue)
12197
{
122-
auto input_platform = stub_input_platform.load();
123-
if (!input_platform)
124-
BOOST_THROW_EXCEPTION(std::runtime_error("No stub input platform available"));
125-
126-
input_platform->platform_dispatchable->add_watch(queue);
98+
platform_dispatchable->add_watch(queue);
12799
}
128100

129101
void mtf::StubInputPlatform::unregister_dispatchable(std::shared_ptr<mir::dispatch::Dispatchable> const& queue)
130102
{
131-
auto input_platform = stub_input_platform.load();
132-
if (!input_platform)
133-
BOOST_THROW_EXCEPTION(std::runtime_error("No stub input platform available"));
134-
135-
input_platform->platform_dispatchable->remove_watch(queue);
103+
platform_dispatchable->remove_watch(queue);
136104
}
137-
138-
std::atomic<mtf::StubInputPlatform*> mtf::StubInputPlatform::stub_input_platform{nullptr};
139-
std::vector<std::weak_ptr<mir::input::InputDevice>> mtf::StubInputPlatform::device_store;
140-
std::mutex mtf::StubInputPlatform::device_store_guard;

0 commit comments

Comments
 (0)