Merge lp:~thomas-voss/trust-store/watch-service-name-owner-changes into lp:trust-store

Proposed by Thomas Voß
Status: Superseded
Proposed branch: lp:~thomas-voss/trust-store/watch-service-name-owner-changes
Merge into: lp:trust-store
Diff against target: 800 lines (+318/-186)
12 files modified
CMakeLists.txt (+2/-2)
debian/changelog (+8/-12)
debian/control (+4/-4)
src/CMakeLists.txt (+3/-0)
src/core/trust/daemon.cpp (+16/-90)
src/core/trust/dbus/agent_registry.h (+38/-0)
src/core/trust/remote/dbus.cpp (+20/-5)
src/core/trust/remote/dbus.h (+7/-1)
src/core/trust/runtime.cpp (+80/-0)
src/core/trust/runtime.h (+73/-0)
tests/CMakeLists.txt (+3/-0)
tests/remote_agent_test.cpp (+64/-72)
To merge this branch: bzr merge lp:~thomas-voss/trust-store/watch-service-name-owner-changes
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+281482@code.launchpad.net

This proposal has been superseded by a proposal from 2016-01-03.

Commit message

core::trust::dbus::Agent::Skeleton now watches for name owner changes, announcing itself
asynchronously if a new name owner is detected.

Description of the change

core::trust::dbus::Agent::Skeleton now watches for name owner changes, announcing itself
asynchronously if a new name owner is detected.

To post a comment you must log in.
138. By Thomas Voß

Make core::trust::Runtime a proper class and do not expose its internals anymore.

139. By Thomas Voß

Address a few minor niggles regarding object lifetimes and noexcept(true) guarantees.

140. By Thomas Voß

Wait a little longer to account for slow builders.

141. By Thomas Voß

Link correct bug report.

Unmerged revisions

141. By Thomas Voß

Link correct bug report.

140. By Thomas Voß

Wait a little longer to account for slow builders.

139. By Thomas Voß

Address a few minor niggles regarding object lifetimes and noexcept(true) guarantees.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-08-31 13:16:20 +0000
+++ CMakeLists.txt 2016-01-03 20:28:56 +0000
@@ -46,8 +46,8 @@
46pkg_check_modules(GLOG libglog REQUIRED)46pkg_check_modules(GLOG libglog REQUIRED)
47pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)47pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)
4848
49set(TRUST_STORE_VERSION_MAJOR 2)49set(TRUST_STORE_VERSION_MAJOR 1)
50set(TRUST_STORE_VERSION_MINOR 0)50set(TRUST_STORE_VERSION_MINOR 1)
51set(TRUST_STORE_VERSION_PATCH 0)51set(TRUST_STORE_VERSION_PATCH 0)
5252
53include(CTest)53include(CTest)
5454
=== modified file 'debian/changelog'
--- debian/changelog 2015-08-31 15:11:26 +0000
+++ debian/changelog 2016-01-03 20:28:56 +0000
@@ -1,18 +1,14 @@
1trust-store (2.0.0+15.10.20150831.3-0ubuntu1) wily; urgency=medium1trust-store (1.1.0+15.04.20151126-0ubuntu1) vivid; urgency=medium
22
3 [ Alfonso Sanchez-Beato (email Canonical) ]3 [ Thomas Voß ]
4 * Merge wily changes upstream4 * Revert bump to major revision 2, vivid (+overlay) still has
5 1.1.0 and gcc 4.9.
56
6 [ CI Train Bot ]7 [ CI Train Bot ]
7 * No-change rebuild.8 * New rebuild forced.
89 * Resync trunk.
9 -- CI Train Bot <ci-train-bot@canonical.com> Mon, 31 Aug 2015 15:11:25 +000010
1011 -- Thomas Voß <ci-train-bot@canonical.com> Thu, 26 Nov 2015 07:32:48 +0000
11trust-store (2.0.0-0ubuntu1) wily; urgency=medium
12
13 * Bump major revision to account for toolchain update. Fixes LP:#1452341
14
15 -- Thomas Voß <thomas.voss@canonical.com> Thu, 23 Jul 2015 09:22:15 +0200
1612
17trust-store (1.1.0+15.04.20150820-0ubuntu1) vivid; urgency=medium13trust-store (1.1.0+15.04.20150820-0ubuntu1) vivid; urgency=medium
1814
1915
=== modified file 'debian/control'
--- debian/control 2015-08-31 13:16:20 +0000
+++ debian/control 2016-01-03 20:28:56 +0000
@@ -30,7 +30,7 @@
30# upstream branch30# upstream branch
31Vcs-Bzr: lp:trust-store31Vcs-Bzr: lp:trust-store
3232
33Package: libtrust-store233Package: libtrust-store1
34Architecture: any34Architecture: any
35Multi-Arch: same35Multi-Arch: same
36Pre-Depends: ${misc:Pre-Depends},36Pre-Depends: ${misc:Pre-Depends},
@@ -48,7 +48,7 @@
48Multi-Arch: same48Multi-Arch: same
49Pre-Depends: ${misc:Pre-Depends},49Pre-Depends: ${misc:Pre-Depends},
50Recommends: libtrust-store-doc,50Recommends: libtrust-store-doc,
51Depends: libtrust-store2 (= ${binary:Version}),51Depends: libtrust-store1 (= ${binary:Version}),
52 ${misc:Depends},52 ${misc:Depends},
53Description: C++11 library for persisting trust requests - dev files53Description: C++11 library for persisting trust requests - dev files
54 Provides a common implementation of a trust store to be used by trusted54 Provides a common implementation of a trust store to be used by trusted
@@ -60,7 +60,7 @@
60Package: trust-store-bin60Package: trust-store-bin
61Section: devel61Section: devel
62Architecture: any62Architecture: any
63Depends: libtrust-store2 (= ${binary:Version}),63Depends: libtrust-store1 (= ${binary:Version}),
64 ${misc:Depends},64 ${misc:Depends},
65Description: Daemon binaries to be used by services.65Description: Daemon binaries to be used by services.
66 Provides a common implementation of a trust store to be used by trusted66 Provides a common implementation of a trust store to be used by trusted
@@ -71,7 +71,7 @@
71Package: trust-store-tests71Package: trust-store-tests
72Section: libdevel72Section: libdevel
73Architecture: any73Architecture: any
74Depends: libtrust-store2 (= ${binary:Version}),74Depends: libtrust-store1 (= ${binary:Version}),
75 ${misc:Depends},75 ${misc:Depends},
76Suggests: libtrust-store-dev,76Suggests: libtrust-store-dev,
77Description: Test files for libtrust-store177Description: Test files for libtrust-store1
7878
=== renamed file 'debian/libtrust-store2.install' => 'debian/libtrust-store1.install'
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2015-08-31 13:16:20 +0000
+++ src/CMakeLists.txt 2016-01-03 20:28:56 +0000
@@ -149,6 +149,9 @@
149 trust-stored149 trust-stored
150150
151 core/trust/daemon.cpp151 core/trust/daemon.cpp
152
153 core/trust/runtime.h
154 core/trust/runtime.cpp
152)155)
153156
154add_executable(157add_executable(
155158
=== modified file 'src/core/trust/daemon.cpp'
--- src/core/trust/daemon.cpp 2015-08-31 14:00:41 +0000
+++ src/core/trust/daemon.cpp 2016-01-03 20:28:56 +0000
@@ -22,6 +22,7 @@
22#include <core/trust/cached_agent.h>22#include <core/trust/cached_agent.h>
23#include <core/trust/expose.h>23#include <core/trust/expose.h>
24#include <core/trust/i18n.h>24#include <core/trust/i18n.h>
25#include <core/trust/runtime.h>
25#include <core/trust/store.h>26#include <core/trust/store.h>
26#include <core/trust/white_listing_agent.h>27#include <core/trust/white_listing_agent.h>
2728
@@ -49,67 +50,6 @@
4950
50namespace51namespace
51{52{
52 struct Runtime
53 {
54 // Do not execute in parallel, serialize
55 // accesses.
56 static constexpr std::size_t concurrency_hint{2};
57
58 // Our evil singleton pattern. Not bad though, we control the
59 // entire executable and rely on automatic cleanup of static
60 // instances.
61 static Runtime& instance()
62 {
63 static Runtime runtime;
64 return runtime;
65 }
66
67 ~Runtime()
68 {
69 io_service.stop();
70
71 if (worker1.joinable())
72 worker1.join();
73
74 if (worker2.joinable())
75 worker2.join();
76 }
77
78 // We trap sig term to ensure a clean shutdown.
79 std::shared_ptr<core::posix::SignalTrap> signal_trap
80 {
81 core::posix::trap_signals_for_all_subsequent_threads(
82 {
83 core::posix::Signal::sig_term,
84 core::posix::Signal::sig_int
85 })
86 };
87
88 // Our io_service instance exposed to remote agents.
89 boost::asio::io_service io_service
90 {
91 concurrency_hint
92 };
93
94 // We keep the io_service alive and introduce some artificial
95 // work.
96 boost::asio::io_service::work keep_alive
97 {
98 io_service
99 };
100
101 // We immediate execute the io_service instance
102 std::thread worker1
103 {
104 std::thread{[this]() { io_service.run(); }}
105 };
106
107 std::thread worker2
108 {
109 std::thread{[this]() { io_service.run(); }}
110 };
111 };
112
113 core::trust::Daemon::Dictionary fill_dictionary_from_unrecognized_options(const Options::parsed_options& parsed_options)53 core::trust::Daemon::Dictionary fill_dictionary_from_unrecognized_options(const Options::parsed_options& parsed_options)
114 {54 {
115 auto unrecognized = Options::collect_unrecognized(55 auto unrecognized = Options::collect_unrecognized(
@@ -170,7 +110,7 @@
170 "Could not create bus for name: " + bus_name110 "Could not create bus for name: " + bus_name
171 };111 };
172112
173 bus->install_executor(core::dbus::asio::make_executor(bus, Runtime::instance().io_service));113 bus->install_executor(core::dbus::asio::make_executor(bus, core::trust::Runtime::instance().io_service));
174114
175 return bus;115 return bus;
176 }116 }
@@ -256,7 +196,7 @@
256 core::trust::remote::posix::Skeleton::Configuration config196 core::trust::remote::posix::Skeleton::Configuration config
257 {197 {
258 agent,198 agent,
259 Runtime::instance().io_service,199 core::trust::Runtime::instance().io_service,
260 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},200 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},
261 core::trust::remote::helpers::proc_stat_start_time_resolver(),201 core::trust::remote::helpers::proc_stat_start_time_resolver(),
262 core::trust::remote::helpers::aa_get_task_con_app_id_resolver(),202 core::trust::remote::helpers::aa_get_task_con_app_id_resolver(),
@@ -289,16 +229,19 @@
289 core::trust::remote::dbus::default_agent_registry_path229 core::trust::remote::dbus::default_agent_registry_path
290 });230 });
291231
232 core::dbus::DBus daemon{bus};
233
292 core::trust::remote::dbus::Agent::Skeleton::Configuration config234 core::trust::remote::dbus::Agent::Skeleton::Configuration config
293 {235 {
294 agent,236 agent,
295 object,237 object,
238 daemon.make_service_watcher(dbus_service_name),
296 service,239 service,
297 bus,240 bus,
298 core::trust::remote::helpers::aa_get_task_con_app_id_resolver()241 core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
299 };242 };
300243
301 return std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(config);244 return std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(std::move(config));
302 }245 }
303 }246 }
304 };247 };
@@ -390,16 +333,6 @@
390// Executes the daemon with the given configuration.333// Executes the daemon with the given configuration.
391core::posix::exit::Status core::trust::Daemon::Skeleton::main(const core::trust::Daemon::Skeleton::Configuration& configuration)334core::posix::exit::Status core::trust::Daemon::Skeleton::main(const core::trust::Daemon::Skeleton::Configuration& configuration)
392{335{
393 Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal)
394 {
395 Runtime::instance().signal_trap->stop();
396 });
397
398 std::thread worker
399 {
400 [configuration]() { configuration.bus->run(); }
401 };
402
403 // Expose the local store to the bus, keeping it exposed for the336 // Expose the local store to the bus, keeping it exposed for the
404 // lifetime of the returned token.337 // lifetime of the returned token.
405 auto token = core::trust::expose_store_to_bus_with_name(338 auto token = core::trust::expose_store_to_bus_with_name(
@@ -407,12 +340,7 @@
407 configuration.bus,340 configuration.bus,
408 configuration.service_name);341 configuration.service_name);
409342
410 Runtime::instance().signal_trap->run();343 core::trust::Runtime::instance().run();
411
412 configuration.bus->stop();
413
414 if (worker.joinable())
415 worker.join();
416344
417 return core::posix::exit::Status::success;345 return core::posix::exit::Status::success;
418}346}
@@ -432,7 +360,7 @@
432360
433 core::trust::remote::posix::Stub::Configuration config361 core::trust::remote::posix::Stub::Configuration config
434 {362 {
435 Runtime::instance().io_service,363 core::trust::Runtime::instance().io_service,
436 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},364 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},
437 core::trust::remote::helpers::proc_stat_start_time_resolver(),365 core::trust::remote::helpers::proc_stat_start_time_resolver(),
438 core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(),366 core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(),
@@ -524,11 +452,16 @@
524{452{
525 Shell(const std::shared_ptr<core::trust::Agent>& agent)453 Shell(const std::shared_ptr<core::trust::Agent>& agent)
526 : agent{agent},454 : agent{agent},
527 stdin{Runtime::instance().io_service, STDIN_FILENO},455 stdin{core::trust::Runtime::instance().io_service, STDIN_FILENO},
528 app_id_resolver{core::trust::remote::helpers::aa_get_task_con_app_id_resolver()}456 app_id_resolver{core::trust::remote::helpers::aa_get_task_con_app_id_resolver()}
529 {457 {
530 }458 }
531459
460 ~Shell()
461 {
462 stop();
463 }
464
532 // Prints out the initial prompt and initiates a read operation on stdin.465 // Prints out the initial prompt and initiates a read operation on stdin.
533 void start()466 void start()
534 {467 {
@@ -607,18 +540,11 @@
607 // We setup our minimal shell here.540 // We setup our minimal shell here.
608 auto shell = std::make_shared<Shell>(configuration.remote.agent);541 auto shell = std::make_shared<Shell>(configuration.remote.agent);
609542
610 Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal)
611 {
612 Runtime::instance().signal_trap->stop();
613 });
614
615 // We start up our shell543 // We start up our shell
616 shell->start();544 shell->start();
617545
618 // Wait until signal arrives.546 // Wait until signal arrives.
619 Runtime::instance().signal_trap->run();547 core::trust::Runtime::instance().run();
620
621 shell->stop();
622548
623 return core::posix::exit::Status::success;549 return core::posix::exit::Status::success;
624}550}
625551
=== modified file 'src/core/trust/dbus/agent_registry.h'
--- src/core/trust/dbus/agent_registry.h 2014-08-04 07:10:52 +0000
+++ src/core/trust/dbus/agent_registry.h 2016-01-03 20:28:56 +0000
@@ -179,6 +179,44 @@
179 locking_agent_registry.register_agent_for_user(uid, skeleton);179 locking_agent_registry.register_agent_for_user(uid, skeleton);
180 }180 }
181181
182 // Calls into the remote implementation to register the given agent implementation.
183 // Throws std::runtime_error and std::logic_error in case of issues.
184 void register_agent_for_user_async(const core::trust::Uid& uid, const std::shared_ptr<core::trust::Agent>& impl, const std::function<void()>& then)
185 {
186 // We sample a path for the given uid
187 auto path = configuration.object_path_generator(uid);
188 // And construct the skeleton instance.
189 auto skeleton = std::shared_ptr<core::trust::dbus::Agent::Skeleton>
190 {
191 new core::trust::dbus::Agent::Skeleton
192 {
193 core::trust::dbus::Agent::Skeleton::Configuration
194 {
195 configuration.service->add_object_for_path(path),
196 configuration.bus,
197 std::bind(&core::trust::Agent::authenticate_request_with_parameters, impl, std::placeholders::_1)
198 }
199 }
200 };
201
202 // And announce the agent.
203 configuration.object->invoke_method_asynchronously_with_callback<
204 Methods::RegisterAgentForUser, void
205 >([this, then, uid, skeleton](const core::dbus::Result<void>& result)
206 {
207 if (result.is_error())
208 {
209 std::cerr << "Failed to register agent for user: " << result.error().print() << std::endl;
210 }
211 else
212 {
213 // All good, update our own state prior to invoking the supplied callback.
214 locking_agent_registry.register_agent_for_user(uid, skeleton);
215 then();
216 }
217 }, uid, path);
218 }
219
182 // Calls into the remote implementation to unregister any agent registered for the given uid.220 // Calls into the remote implementation to unregister any agent registered for the given uid.
183 // Throws std::runtime_error and std::logic_error in case of issues.221 // Throws std::runtime_error and std::logic_error in case of issues.
184 void unregister_agent_for_user(const core::trust::Uid& uid) override222 void unregister_agent_for_user(const core::trust::Uid& uid) override
185223
=== modified file 'src/core/trust/remote/dbus.cpp'
--- src/core/trust/remote/dbus.cpp 2014-07-29 17:00:35 +0000
+++ src/core/trust/remote/dbus.cpp 2016-01-03 20:28:56 +0000
@@ -19,6 +19,7 @@
19#include <core/trust/remote/dbus.h>19#include <core/trust/remote/dbus.h>
2020
21#include <core/trust/dbus_agent.h>21#include <core/trust/dbus_agent.h>
22#include <core/trust/runtime.h>
2223
23core::trust::remote::dbus::Agent::Stub::Stub(const core::trust::remote::dbus::Agent::Stub::Configuration& configuration)24core::trust::remote::dbus::Agent::Stub::Stub(const core::trust::remote::dbus::Agent::Stub::Configuration& configuration)
24 : agent_registry_skeleton25 : agent_registry_skeleton
@@ -43,20 +44,34 @@
43 return agent->authenticate_request_with_parameters(parameters);44 return agent->authenticate_request_with_parameters(parameters);
44}45}
4546
46core::trust::remote::dbus::Agent::Skeleton::Skeleton(const core::trust::remote::dbus::Agent::Skeleton::Configuration& configuration)47core::trust::remote::dbus::Agent::Skeleton::Skeleton(core::trust::remote::dbus::Agent::Skeleton::Configuration configuration)
47 : core::trust::remote::Agent::Skeleton{configuration.impl},48 : core::trust::remote::Agent::Skeleton{configuration.impl},
49 config(std::move(configuration)),
48 agent_registry_stub50 agent_registry_stub
49 {51 {
50 core::trust::dbus::AgentRegistry::Stub::Configuration52 core::trust::dbus::AgentRegistry::Stub::Configuration
51 {53 {
52 configuration.agent_registry_object,54 config.agent_registry_object,
53 core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(),55 core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(),
54 configuration.service,56 config.service,
55 configuration.bus57 config.bus
56 }58 }
57 }59 }
58{60{
59 agent_registry_stub.register_agent_for_user(core::trust::Uid{::getuid()}, configuration.impl);61 agent_registry_stub.register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, []()
62 {
63 std::cout << "Error registering agent for user." << std::endl;
64 });
65
66 // We don't have to track the lifetime of "this" as config.agent_registry_watcher is owned
67 // by "this".
68 config.agent_registry_watcher->service_registered().connect([this]()
69 {
70 agent_registry_stub.register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, []()
71 {
72 std::cout << "Error registering agent for user." << std::endl;
73 });
74 });
60}75}
6176
62core::trust::Request::Answer core::trust::remote::dbus::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters)77core::trust::Request::Answer core::trust::remote::dbus::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters)
6378
=== modified file 'src/core/trust/remote/dbus.h'
--- src/core/trust/remote/dbus.h 2014-08-04 07:57:05 +0000
+++ src/core/trust/remote/dbus.h 2016-01-03 20:28:56 +0000
@@ -25,6 +25,8 @@
25#include <core/trust/dbus/agent.h>25#include <core/trust/dbus/agent.h>
26#include <core/trust/dbus/agent_registry.h>26#include <core/trust/dbus/agent_registry.h>
2727
28#include <core/dbus/service_watcher.h>
29
28#include <unistd.h>30#include <unistd.h>
29#include <sys/types.h>31#include <sys/types.h>
3032
@@ -86,6 +88,8 @@
86 std::shared_ptr<Agent> impl;88 std::shared_ptr<Agent> impl;
87 // The remote object implementing core.trust.dbus.AgentRegistry.89 // The remote object implementing core.trust.dbus.AgentRegistry.
88 core::dbus::Object::Ptr agent_registry_object;90 core::dbus::Object::Ptr agent_registry_object;
91 // The watcher monitoring the remote object implementing core.trust.dbus.AgentRegistry.
92 std::unique_ptr<core::dbus::ServiceWatcher> agent_registry_watcher;
89 // The service that objects implementing core.trust.dbus.Agent should be added to.93 // The service that objects implementing core.trust.dbus.Agent should be added to.
90 core::dbus::Service::Ptr service;94 core::dbus::Service::Ptr service;
91 // The underlying bus instance.95 // The underlying bus instance.
@@ -95,11 +99,13 @@
95 };99 };
96100
97 // Constructs a new Skeleton instance, installing impl for handling actual requests.101 // Constructs a new Skeleton instance, installing impl for handling actual requests.
98 Skeleton(const Configuration& configuration);102 Skeleton(Configuration configuration);
99103
100 // From core::trust::Agent, dispatches to the actual implementation.104 // From core::trust::Agent, dispatches to the actual implementation.
101 core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters);105 core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters);
102106
107 // Store all creation-time parameters.
108 Configuration config;
103 // Stub for accessing the remote agent registry.109 // Stub for accessing the remote agent registry.
104 core::trust::dbus::AgentRegistry::Stub agent_registry_stub;110 core::trust::dbus::AgentRegistry::Stub agent_registry_stub;
105 };111 };
106112
=== added file 'src/core/trust/runtime.cpp'
--- src/core/trust/runtime.cpp 1970-01-01 00:00:00 +0000
+++ src/core/trust/runtime.cpp 2016-01-03 20:28:56 +0000
@@ -0,0 +1,80 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <core/trust/runtime.h>
20
21#include <iostream>
22#include <stdexcept>
23
24namespace
25{
26void execute_and_never_throw(boost::asio::io_service& ios) noexcept(true)
27{
28 while (true)
29 {
30 try
31 {
32 ios.run();
33 break;
34 }
35 catch (const std::exception& e)
36 {
37 std::cerr << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl;
38 }
39 catch (...)
40 {
41 std::cerr << __PRETTY_FUNCTION__ << ": unknown exception" << std::endl;
42 }
43 }
44}
45}
46
47core::trust::Runtime& core::trust::Runtime::instance()
48{
49 static Runtime runtime;
50 return runtime;
51}
52
53core::trust::Runtime::Runtime()
54 : signal_trap{core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term, core::posix::Signal::sig_int})},
55 keep_alive{io_service}
56{
57 for (std::size_t i = 0; i < Runtime::concurrency_hint; i++)
58 {
59 pool.emplace_back(execute_and_never_throw, std::ref(io_service));
60 }
61
62 signal_trap->signal_raised().connect([this](const core::posix::Signal&)
63 {
64 signal_trap->stop();
65 });
66}
67
68core::trust::Runtime::~Runtime()
69{
70 io_service.stop();
71
72 for (auto& worker : pool)
73 if (worker.joinable())
74 worker.join();
75}
76
77void core::trust::Runtime::run()
78{
79 signal_trap->run();
80}
081
=== added file 'src/core/trust/runtime.h'
--- src/core/trust/runtime.h 1970-01-01 00:00:00 +0000
+++ src/core/trust/runtime.h 2016-01-03 20:28:56 +0000
@@ -0,0 +1,73 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#ifndef CORE_TRUST_RUNTIME_H_
20#define CORE_TRUST_RUNTIME_H_
21
22#include <core/posix/signal.h>
23
24#include <boost/asio.hpp>
25
26#include <memory>
27#include <thread>
28#include <vector>
29
30namespace core
31{
32namespace trust
33{
34// A Runtime maintains a pool of workers enabling
35// implementations to dispatch invocations and have their
36// ready handlers automatically executed.
37struct Runtime
38{
39 // Do not execute in parallel, serialize
40 // accesses.
41 static constexpr std::size_t concurrency_hint{2};
42
43 // Our evil singleton pattern. Not bad though, we control the
44 // entire executable and rely on automatic cleanup of static
45 // instances.
46 static Runtime& instance();
47
48 Runtime();
49
50 // Gracefully shuts down operations.
51 ~Runtime() noexcept(true);
52
53 // run blocks until either stop is called or a
54 // signal requesting graceful shutdown is received.
55 void run();
56
57 // We trap sig term to ensure a clean shutdown.
58 std::shared_ptr<core::posix::SignalTrap> signal_trap;
59
60 // Our io_service instance exposed to remote agents.
61 boost::asio::io_service io_service;
62
63 // We keep the io_service alive and introduce some artificial
64 // work.
65 boost::asio::io_service::work keep_alive;
66
67 // We execute the io_service on a pool of worker threads.
68 std::vector<std::thread> pool;
69};
70}
71}
72
73#endif // CORE_TRUST_RUNTIME_H_
074
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2014-11-14 12:17:24 +0000
+++ tests/CMakeLists.txt 2016-01-03 20:28:56 +0000
@@ -46,6 +46,9 @@
46add_executable(46add_executable(
47 remote_agent_test47 remote_agent_test
48 remote_agent_test.cpp48 remote_agent_test.cpp
49
50 ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.h
51 ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.cpp
49)52)
5053
51add_executable(54add_executable(
5255
=== modified file 'tests/remote_agent_test.cpp'
--- tests/remote_agent_test.cpp 2015-08-14 09:53:12 +0000
+++ tests/remote_agent_test.cpp 2016-01-03 20:28:56 +0000
@@ -30,6 +30,8 @@
30#include <core/dbus/asio/executor.h>30#include <core/dbus/asio/executor.h>
31#include <core/dbus/fixture.h>31#include <core/dbus/fixture.h>
3232
33#include <core/trust/runtime.h>
34
33#include <gmock/gmock.h>35#include <gmock/gmock.h>
34#include <gtest/gtest.h>36#include <gtest/gtest.h>
3537
@@ -792,6 +794,12 @@
792{794{
793struct DBus : public core::dbus::testing::Fixture795struct DBus : public core::dbus::testing::Fixture
794{796{
797 core::dbus::Bus::Ptr session_bus_with_executor()
798 {
799 auto sb = session_bus();
800 sb->install_executor(core::dbus::asio::make_executor(sb, core::trust::Runtime::instance().io_service));
801 return sb;
802 }
795};803};
796804
797std::string service_name805std::string service_name
@@ -804,10 +812,6 @@
804{812{
805 using namespace ::testing;813 using namespace ::testing;
806814
807 core::testing::CrossProcessSync
808 stub_ready, // signals stub --| I'm ready |--> skeleton
809 skeleton_ready; // signals skeleton --| I'm ready |--> stub
810
811 auto app = core::posix::fork([]()815 auto app = core::posix::fork([]()
812 {816 {
813 while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500});817 while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500});
@@ -825,7 +829,50 @@
825 const core::trust::Uid app_uid{::getuid()};829 const core::trust::Uid app_uid{::getuid()};
826 const core::trust::Pid app_pid{app.pid()};830 const core::trust::Pid app_pid{app.pid()};
827831
828 auto stub = core::posix::fork([this, app_uid, app_pid, answer, &stub_ready, &skeleton_ready]()832 auto skeleton = core::posix::fork([this, answer]()
833 {
834 auto bus = session_bus_with_executor();
835
836 // We have to rely on a MockAgent to break the dependency on a running Mir instance.
837 auto mock_agent = std::make_shared<::testing::NiceMock<MockAgent>>();
838
839 ON_CALL(*mock_agent, authenticate_request_with_parameters(_))
840 .WillByDefault(Return(answer));
841
842 std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
843
844 auto service = core::dbus::Service::use_service(bus, dbus_service_name);
845 auto object = service->object_for_path(core::dbus::types::ObjectPath
846 {
847 core::trust::remote::dbus::default_agent_registry_path
848 });
849
850 core::dbus::DBus daemon{bus};
851
852 core::trust::remote::dbus::Agent::Skeleton::Configuration config
853 {
854 mock_agent,
855 object,
856 daemon.make_service_watcher(dbus_service_name),
857 service,
858 bus,
859 core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
860 };
861
862 auto skeleton = std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(std::move(config));
863
864 core::trust::Runtime::instance().run();
865 return core::posix::exit::Status::success;
866 }, core::posix::StandardStream::empty);
867
868
869 // stubf models a trusted helper, with the following simplified
870 // mode of operation:
871 // (1.) Helper claims its unique name on the bus.
872 // (2.) Helper installs an AgentRegistry::Skeleton.
873 // (3.) Helper learns about per-user trust::Agent instances on the bus.
874 // (4.) Helper issues requests for authentication.
875 auto stubf = [this, app_uid, app_pid, answer]()
829 {876 {
830 core::trust::Agent::RequestParameters ref_params877 core::trust::Agent::RequestParameters ref_params
831 {878 {
@@ -836,10 +883,7 @@
836 "just an example description"883 "just an example description"
837 };884 };
838885
839 auto bus = session_bus();886 auto bus = session_bus_with_executor();
840 bus->install_executor(core::dbus::asio::make_executor(bus));
841
842 std::thread worker{[bus]() { bus->run(); }};
843887
844 std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;888 std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
845889
@@ -857,76 +901,24 @@
857901
858 auto stub = std::make_shared<core::trust::remote::dbus::Agent::Stub>(config);902 auto stub = std::make_shared<core::trust::remote::dbus::Agent::Stub>(config);
859903
860 stub_ready.try_signal_ready_for(std::chrono::milliseconds{1000});904 std::this_thread::sleep_for(std::chrono::seconds(1));
861 skeleton_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000});
862905
863 for (unsigned int i = 0; i < 100; i++)906 for (unsigned int i = 0; i < 100; i++)
864 EXPECT_EQ(answer, stub->authenticate_request_with_parameters(ref_params));907 EXPECT_EQ(answer, stub->authenticate_request_with_parameters(ref_params));
865908
866 bus->stop();
867
868 if (worker.joinable())
869 worker.join();
870
871 return Test::HasFailure() ?909 return Test::HasFailure() ?
872 core::posix::exit::Status::failure :910 core::posix::exit::Status::failure :
873 core::posix::exit::Status::success;911 core::posix::exit::Status::success;
874 }, core::posix::StandardStream::empty);912 };
875913
876 auto skeleton = core::posix::fork([this, answer, &stub_ready, &skeleton_ready]()914 std::this_thread::sleep_for(std::chrono::seconds(2));
877 {915 auto stub = core::posix::fork(stubf, core::posix::StandardStream::empty);
878 auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});916 EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
879917
880 trap->signal_raised().connect([trap](core::posix::Signal)918 std::this_thread::sleep_for(std::chrono::seconds(2));
881 {919 stub = core::posix::fork(stubf, core::posix::StandardStream::empty);
882 trap->stop();920 EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
883 });921
884
885 auto bus = session_bus();
886 bus->install_executor(core::dbus::asio::make_executor(bus));
887
888 std::thread worker{[bus]() { bus->run(); }};
889
890 // We have to rely on a MockAgent to break the dependency on a running Mir instance.
891 auto mock_agent = std::make_shared<::testing::NiceMock<MockAgent>>();
892
893 ON_CALL(*mock_agent, authenticate_request_with_parameters(_))
894 .WillByDefault(Return(answer));
895
896 std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
897
898 stub_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000});
899
900 auto service = core::dbus::Service::use_service(bus, dbus_service_name);
901 auto object = service->object_for_path(core::dbus::types::ObjectPath
902 {
903 core::trust::remote::dbus::default_agent_registry_path
904 });
905
906 core::trust::remote::dbus::Agent::Skeleton::Configuration config
907 {
908 mock_agent,
909 object,
910 service,
911 bus,
912 core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
913 };
914
915 auto skeleton = std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(config);
916
917 skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000});
918
919 trap->run();
920
921 bus->stop();
922
923 if (worker.joinable())
924 worker.join();
925
926 return core::posix::exit::Status::success;
927 }, core::posix::StandardStream::empty);
928
929 EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
930 skeleton.send_signal_or_throw(core::posix::Signal::sig_term);922 skeleton.send_signal_or_throw(core::posix::Signal::sig_term);
931 EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced)));923 EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced)));
932924

Subscribers

People subscribed via source and target branches