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

Proposed by Thomas Voß
Status: Needs review
Proposed branch: lp:~thomas-voss/trust-store/watch-service-name-owner-changes
Merge into: lp:trust-store/15.04
Diff against target: 846 lines (+368/-186)
10 files modified
src/CMakeLists.txt (+3/-0)
src/core/trust/daemon.cpp (+18/-92)
src/core/trust/dbus/agent_registry.h (+54/-5)
src/core/trust/remote/dbus.cpp (+21/-9)
src/core/trust/remote/dbus.h (+8/-2)
src/core/trust/runtime.cpp (+105/-0)
src/core/trust/runtime.h (+88/-0)
tests/CMakeLists.txt (+3/-0)
tests/dbus_test.cpp (+4/-6)
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+281483@code.launchpad.net

This proposal supersedes 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.

138. By Thomas Voß

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

137. By Thomas Voß

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2015-08-31 13:16:20 +0000
3+++ src/CMakeLists.txt 2016-01-04 15:02:54 +0000
4@@ -149,6 +149,9 @@
5 trust-stored
6
7 core/trust/daemon.cpp
8+
9+ core/trust/runtime.h
10+ core/trust/runtime.cpp
11 )
12
13 add_executable(
14
15=== modified file 'src/core/trust/daemon.cpp'
16--- src/core/trust/daemon.cpp 2015-08-31 14:00:41 +0000
17+++ src/core/trust/daemon.cpp 2016-01-04 15:02:54 +0000
18@@ -22,6 +22,7 @@
19 #include <core/trust/cached_agent.h>
20 #include <core/trust/expose.h>
21 #include <core/trust/i18n.h>
22+#include <core/trust/runtime.h>
23 #include <core/trust/store.h>
24 #include <core/trust/white_listing_agent.h>
25
26@@ -49,67 +50,6 @@
27
28 namespace
29 {
30- struct Runtime
31- {
32- // Do not execute in parallel, serialize
33- // accesses.
34- static constexpr std::size_t concurrency_hint{2};
35-
36- // Our evil singleton pattern. Not bad though, we control the
37- // entire executable and rely on automatic cleanup of static
38- // instances.
39- static Runtime& instance()
40- {
41- static Runtime runtime;
42- return runtime;
43- }
44-
45- ~Runtime()
46- {
47- io_service.stop();
48-
49- if (worker1.joinable())
50- worker1.join();
51-
52- if (worker2.joinable())
53- worker2.join();
54- }
55-
56- // We trap sig term to ensure a clean shutdown.
57- std::shared_ptr<core::posix::SignalTrap> signal_trap
58- {
59- core::posix::trap_signals_for_all_subsequent_threads(
60- {
61- core::posix::Signal::sig_term,
62- core::posix::Signal::sig_int
63- })
64- };
65-
66- // Our io_service instance exposed to remote agents.
67- boost::asio::io_service io_service
68- {
69- concurrency_hint
70- };
71-
72- // We keep the io_service alive and introduce some artificial
73- // work.
74- boost::asio::io_service::work keep_alive
75- {
76- io_service
77- };
78-
79- // We immediate execute the io_service instance
80- std::thread worker1
81- {
82- std::thread{[this]() { io_service.run(); }}
83- };
84-
85- std::thread worker2
86- {
87- std::thread{[this]() { io_service.run(); }}
88- };
89- };
90-
91 core::trust::Daemon::Dictionary fill_dictionary_from_unrecognized_options(const Options::parsed_options& parsed_options)
92 {
93 auto unrecognized = Options::collect_unrecognized(
94@@ -170,7 +110,7 @@
95 "Could not create bus for name: " + bus_name
96 };
97
98- bus->install_executor(core::dbus::asio::make_executor(bus, Runtime::instance().io_service));
99+ bus->install_executor(core::trust::Runtime::instance().make_executor_for_bus(bus));
100
101 return bus;
102 }
103@@ -256,7 +196,7 @@
104 core::trust::remote::posix::Skeleton::Configuration config
105 {
106 agent,
107- Runtime::instance().io_service,
108+ core::trust::Runtime::instance().service(),
109 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},
110 core::trust::remote::helpers::proc_stat_start_time_resolver(),
111 core::trust::remote::helpers::aa_get_task_con_app_id_resolver(),
112@@ -289,16 +229,19 @@
113 core::trust::remote::dbus::default_agent_registry_path
114 });
115
116+ core::dbus::DBus daemon{bus};
117+
118 core::trust::remote::dbus::Agent::Skeleton::Configuration config
119 {
120 agent,
121 object,
122+ daemon.make_service_watcher(dbus_service_name),
123 service,
124 bus,
125 core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
126 };
127
128- return std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(config);
129+ return std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(std::move(config));
130 }
131 }
132 };
133@@ -390,16 +333,6 @@
134 // Executes the daemon with the given configuration.
135 core::posix::exit::Status core::trust::Daemon::Skeleton::main(const core::trust::Daemon::Skeleton::Configuration& configuration)
136 {
137- Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal)
138- {
139- Runtime::instance().signal_trap->stop();
140- });
141-
142- std::thread worker
143- {
144- [configuration]() { configuration.bus->run(); }
145- };
146-
147 // Expose the local store to the bus, keeping it exposed for the
148 // lifetime of the returned token.
149 auto token = core::trust::expose_store_to_bus_with_name(
150@@ -407,12 +340,7 @@
151 configuration.bus,
152 configuration.service_name);
153
154- Runtime::instance().signal_trap->run();
155-
156- configuration.bus->stop();
157-
158- if (worker.joinable())
159- worker.join();
160+ core::trust::Runtime::instance().run();
161
162 return core::posix::exit::Status::success;
163 }
164@@ -432,7 +360,7 @@
165
166 core::trust::remote::posix::Stub::Configuration config
167 {
168- Runtime::instance().io_service,
169+ core::trust::Runtime::instance().service(),
170 boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")},
171 core::trust::remote::helpers::proc_stat_start_time_resolver(),
172 core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(),
173@@ -522,13 +450,18 @@
174 // A user can feed a request to the stub.
175 struct Shell : public std::enable_shared_from_this<Shell>
176 {
177- Shell(const std::shared_ptr<core::trust::Agent>& agent)
178+ Shell(const std::shared_ptr<core::trust::Agent>& agent, boost::asio::io_service& ios)
179 : agent{agent},
180- stdin{Runtime::instance().io_service, STDIN_FILENO},
181+ stdin{ios, STDIN_FILENO},
182 app_id_resolver{core::trust::remote::helpers::aa_get_task_con_app_id_resolver()}
183 {
184 }
185
186+ ~Shell()
187+ {
188+ stop();
189+ }
190+
191 // Prints out the initial prompt and initiates a read operation on stdin.
192 void start()
193 {
194@@ -605,20 +538,13 @@
195 core::posix::exit::Status core::trust::Daemon::Stub::main(const core::trust::Daemon::Stub::Configuration& configuration)
196 {
197 // We setup our minimal shell here.
198- auto shell = std::make_shared<Shell>(configuration.remote.agent);
199-
200- Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal)
201- {
202- Runtime::instance().signal_trap->stop();
203- });
204+ auto shell = std::make_shared<Shell>(configuration.remote.agent, core::trust::Runtime::instance().service());
205
206 // We start up our shell
207 shell->start();
208
209 // Wait until signal arrives.
210- Runtime::instance().signal_trap->run();
211-
212- shell->stop();
213+ core::trust::Runtime::instance().run();
214
215 return core::posix::exit::Status::success;
216 }
217
218=== modified file 'src/core/trust/dbus/agent_registry.h'
219--- src/core/trust/dbus/agent_registry.h 2014-08-04 07:10:52 +0000
220+++ src/core/trust/dbus/agent_registry.h 2016-01-04 15:02:54 +0000
221@@ -114,8 +114,10 @@
222 };
223
224 // A DBus stub implementation of core::trust::AgentRegistry.
225- struct Stub : public core::trust::Agent::Registry
226+ class Stub : public std::enable_shared_from_this<Stub>,
227+ public core::trust::Agent::Registry
228 {
229+ public:
230 // Functor for generating unique object paths.
231 typedef std::function<core::dbus::types::ObjectPath(const core::trust::Uid&)> ObjectPathGenerator;
232
233@@ -139,12 +141,12 @@
234 core::dbus::Service::Ptr service;
235 // The underlying bus instance.
236 core::dbus::Bus::Ptr bus;
237- };
238+ };
239
240- // Initializes stub access to the Stub.
241- Stub(const Configuration& configuration)
242- : configuration(configuration)
243+ // create returns a new shared Stub instance for configuration.
244+ static std::shared_ptr<Stub> create(const Configuration& configuration)
245 {
246+ return std::shared_ptr<Stub>(new Stub(configuration));
247 }
248
249 // Calls into the remote implementation to register the given agent implementation.
250@@ -179,6 +181,46 @@
251 locking_agent_registry.register_agent_for_user(uid, skeleton);
252 }
253
254+ // Calls into the remote implementation to register the given agent implementation.
255+ // Throws std::runtime_error and std::logic_error in case of issues.
256+ void register_agent_for_user_async(const core::trust::Uid& uid, const std::shared_ptr<core::trust::Agent>& impl, const std::function<void()>& then)
257+ {
258+ // We sample a path for the given uid
259+ auto path = configuration.object_path_generator(uid);
260+ // And construct the skeleton instance.
261+ auto skeleton = std::shared_ptr<core::trust::dbus::Agent::Skeleton>
262+ {
263+ new core::trust::dbus::Agent::Skeleton
264+ {
265+ core::trust::dbus::Agent::Skeleton::Configuration
266+ {
267+ configuration.service->add_object_for_path(path),
268+ configuration.bus,
269+ std::bind(&core::trust::Agent::authenticate_request_with_parameters, impl, std::placeholders::_1)
270+ }
271+ }
272+ };
273+
274+ auto sp = shared_from_this();
275+
276+ // And announce the agent.
277+ configuration.object->invoke_method_asynchronously_with_callback<
278+ Methods::RegisterAgentForUser, void
279+ >([this, sp, then, uid, skeleton](const core::dbus::Result<void>& result)
280+ {
281+ if (result.is_error())
282+ {
283+ std::cerr << "Failed to register agent for user: " << result.error().print() << std::endl;
284+ }
285+ else
286+ {
287+ // All good, update our own state prior to invoking the supplied callback.
288+ locking_agent_registry.register_agent_for_user(uid, skeleton);
289+ then();
290+ }
291+ }, uid, path);
292+ }
293+
294 // Calls into the remote implementation to unregister any agent registered for the given uid.
295 // Throws std::runtime_error and std::logic_error in case of issues.
296 void unregister_agent_for_user(const core::trust::Uid& uid) override
297@@ -195,6 +237,13 @@
298 };
299 }
300
301+ private:
302+ // Initializes stub access to the Stub.
303+ Stub(const Configuration& configuration)
304+ : configuration(configuration)
305+ {
306+ }
307+
308 // We just store all creation-time arguments.
309 Configuration configuration;
310 // Our local registry of agents
311
312=== modified file 'src/core/trust/remote/dbus.cpp'
313--- src/core/trust/remote/dbus.cpp 2014-07-29 17:00:35 +0000
314+++ src/core/trust/remote/dbus.cpp 2016-01-04 15:02:54 +0000
315@@ -19,6 +19,7 @@
316 #include <core/trust/remote/dbus.h>
317
318 #include <core/trust/dbus_agent.h>
319+#include <core/trust/runtime.h>
320
321 core::trust::remote::dbus::Agent::Stub::Stub(const core::trust::remote::dbus::Agent::Stub::Configuration& configuration)
322 : agent_registry_skeleton
323@@ -43,20 +44,31 @@
324 return agent->authenticate_request_with_parameters(parameters);
325 }
326
327-core::trust::remote::dbus::Agent::Skeleton::Skeleton(const core::trust::remote::dbus::Agent::Skeleton::Configuration& configuration)
328+core::trust::remote::dbus::Agent::Skeleton::Skeleton(core::trust::remote::dbus::Agent::Skeleton::Configuration configuration)
329 : core::trust::remote::Agent::Skeleton{configuration.impl},
330+ config(std::move(configuration)),
331 agent_registry_stub
332 {
333- core::trust::dbus::AgentRegistry::Stub::Configuration
334- {
335- configuration.agent_registry_object,
336- core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(),
337- configuration.service,
338- configuration.bus
339- }
340+ core::trust::dbus::AgentRegistry::Stub::create(
341+ core::trust::dbus::AgentRegistry::Stub::Configuration
342+ {
343+ config.agent_registry_object,
344+ core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(),
345+ config.service,
346+ config.bus
347+ })
348 }
349 {
350- agent_registry_stub.register_agent_for_user(core::trust::Uid{::getuid()}, configuration.impl);
351+ static const auto printing_cb = []() { std::cout << "Successfully registered agent for user." << std::endl; };
352+
353+ agent_registry_stub->register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, printing_cb);
354+
355+ // We don't have to track the lifetime of "this" as config.agent_registry_watcher is owned
356+ // by "this".
357+ config.agent_registry_watcher->service_registered().connect([this]()
358+ {
359+ agent_registry_stub->register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, printing_cb);
360+ });
361 }
362
363 core::trust::Request::Answer core::trust::remote::dbus::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters)
364
365=== modified file 'src/core/trust/remote/dbus.h'
366--- src/core/trust/remote/dbus.h 2014-08-04 07:57:05 +0000
367+++ src/core/trust/remote/dbus.h 2016-01-04 15:02:54 +0000
368@@ -25,6 +25,8 @@
369 #include <core/trust/dbus/agent.h>
370 #include <core/trust/dbus/agent_registry.h>
371
372+#include <core/dbus/service_watcher.h>
373+
374 #include <unistd.h>
375 #include <sys/types.h>
376
377@@ -86,6 +88,8 @@
378 std::shared_ptr<Agent> impl;
379 // The remote object implementing core.trust.dbus.AgentRegistry.
380 core::dbus::Object::Ptr agent_registry_object;
381+ // The watcher monitoring the remote object implementing core.trust.dbus.AgentRegistry.
382+ std::unique_ptr<core::dbus::ServiceWatcher> agent_registry_watcher;
383 // The service that objects implementing core.trust.dbus.Agent should be added to.
384 core::dbus::Service::Ptr service;
385 // The underlying bus instance.
386@@ -95,13 +99,15 @@
387 };
388
389 // Constructs a new Skeleton instance, installing impl for handling actual requests.
390- Skeleton(const Configuration& configuration);
391+ Skeleton(Configuration configuration);
392
393 // From core::trust::Agent, dispatches to the actual implementation.
394 core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters);
395
396+ // Store all creation-time parameters.
397+ Configuration config;
398 // Stub for accessing the remote agent registry.
399- core::trust::dbus::AgentRegistry::Stub agent_registry_stub;
400+ std::shared_ptr<core::trust::dbus::AgentRegistry::Stub> agent_registry_stub;
401 };
402 };
403 }
404
405=== added file 'src/core/trust/runtime.cpp'
406--- src/core/trust/runtime.cpp 1970-01-01 00:00:00 +0000
407+++ src/core/trust/runtime.cpp 2016-01-04 15:02:54 +0000
408@@ -0,0 +1,105 @@
409+/*
410+ * Copyright © 2016 Canonical Ltd.
411+ *
412+ * This program is free software: you can redistribute it and/or modify it
413+ * under the terms of the GNU Lesser General Public License version 3,
414+ * as published by the Free Software Foundation.
415+ *
416+ * This program is distributed in the hope that it will be useful,
417+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
418+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
419+ * GNU Lesser General Public License for more details.
420+ *
421+ * You should have received a copy of the GNU Lesser General Public License
422+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
423+ *
424+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
425+ */
426+
427+#include <core/trust/runtime.h>
428+
429+#include <core/dbus/asio/executor.h>
430+
431+#include <iostream>
432+#include <stdexcept>
433+
434+namespace
435+{
436+void execute_and_never_throw(boost::asio::io_service& ios) noexcept(true)
437+{
438+ while (true)
439+ {
440+ try
441+ {
442+ ios.run();
443+ break;
444+ }
445+ catch (const std::exception& e)
446+ {
447+ std::cerr << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl;
448+ }
449+ catch (...)
450+ {
451+ std::cerr << __PRETTY_FUNCTION__ << ": unknown exception" << std::endl;
452+ }
453+ }
454+}
455+}
456+
457+core::trust::Runtime& core::trust::Runtime::instance()
458+{
459+ static Runtime runtime;
460+ return runtime;
461+}
462+
463+core::trust::Runtime::Runtime()
464+ : signal_trap{core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term, core::posix::Signal::sig_int})},
465+ keep_alive{io_service}
466+{
467+ for (std::size_t i = 0; i < Runtime::concurrency_hint; i++)
468+ {
469+ pool.emplace_back(execute_and_never_throw, std::ref(io_service));
470+ }
471+
472+ signal_trap->signal_raised().connect([this](const core::posix::Signal&)
473+ {
474+ stop();
475+ });
476+}
477+
478+core::trust::Runtime::~Runtime()
479+{
480+ try
481+ {
482+ io_service.stop();
483+
484+ for (auto& worker : pool)
485+ if (worker.joinable())
486+ worker.join();
487+ }
488+ catch (...)
489+ {
490+ // Empty on purpose. We just have to
491+ // fulfill the noexcept(true) guarantee.
492+ }
493+}
494+
495+void core::trust::Runtime::run()
496+{
497+ signal_trap->run();
498+}
499+
500+void core::trust::Runtime::stop()
501+{
502+ signal_trap->stop();
503+}
504+
505+boost::asio::io_service& core::trust::Runtime::service()
506+{
507+ return io_service;
508+}
509+
510+core::dbus::Executor::Ptr core::trust::Runtime::make_executor_for_bus(const core::dbus::Bus::Ptr& bus)
511+{
512+ return core::dbus::asio::make_executor(bus, io_service);
513+}
514
515=== added file 'src/core/trust/runtime.h'
516--- src/core/trust/runtime.h 1970-01-01 00:00:00 +0000
517+++ src/core/trust/runtime.h 2016-01-04 15:02:54 +0000
518@@ -0,0 +1,88 @@
519+/*
520+ * Copyright © 2016 Canonical Ltd.
521+ *
522+ * This program is free software: you can redistribute it and/or modify it
523+ * under the terms of the GNU Lesser General Public License version 3,
524+ * as published by the Free Software Foundation.
525+ *
526+ * This program is distributed in the hope that it will be useful,
527+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
528+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
529+ * GNU Lesser General Public License for more details.
530+ *
531+ * You should have received a copy of the GNU Lesser General Public License
532+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
533+ *
534+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
535+ */
536+
537+#ifndef CORE_TRUST_RUNTIME_H_
538+#define CORE_TRUST_RUNTIME_H_
539+
540+#include <core/posix/signal.h>
541+
542+#include <core/dbus/bus.h>
543+#include <core/dbus/executor.h>
544+
545+#include <boost/asio.hpp>
546+
547+#include <memory>
548+#include <thread>
549+#include <vector>
550+
551+namespace core
552+{
553+namespace trust
554+{
555+// A Runtime maintains a pool of workers enabling
556+// implementations to dispatch invocations and have their
557+// ready handlers automatically executed.
558+class Runtime
559+{
560+public:
561+ // Do not execute in parallel, serialize
562+ // accesses.
563+ static constexpr std::size_t concurrency_hint{2};
564+
565+ // Our evil singleton pattern. Not bad though, we control the
566+ // entire executable and rely on automatic cleanup of static
567+ // instances.
568+ static Runtime& instance();
569+
570+ // Gracefully shuts down operations.
571+ ~Runtime() noexcept(true);
572+
573+ // run blocks until either stop is called or a
574+ // signal requesting graceful shutdown is received.
575+ void run();
576+
577+ // requests the runtime to shut down, does not block.
578+ void stop();
579+
580+ // Returns a mutable reference to the underlying boost::asio::io_service
581+ // powering the runtime's reactor.
582+ boost::asio::io_service& service();
583+
584+ // Creates an executor for a bus instance hooking into this Runtime instance.
585+ core::dbus::Executor::Ptr make_executor_for_bus(const core::dbus::Bus::Ptr& bus);
586+
587+private:
588+ Runtime();
589+
590+ // We trap sig term to ensure a clean shutdown.
591+ std::shared_ptr<core::posix::SignalTrap> signal_trap;
592+
593+ // Our io_service instance exposed to remote agents.
594+ boost::asio::io_service io_service;
595+
596+ // We keep the io_service alive and introduce some artificial
597+ // work.
598+ boost::asio::io_service::work keep_alive;
599+
600+ // We execute the io_service on a pool of worker threads.
601+ std::vector<std::thread> pool;
602+};
603+}
604+}
605+
606+#endif // CORE_TRUST_RUNTIME_H_
607
608=== modified file 'tests/CMakeLists.txt'
609--- tests/CMakeLists.txt 2014-11-14 12:17:24 +0000
610+++ tests/CMakeLists.txt 2016-01-04 15:02:54 +0000
611@@ -46,6 +46,9 @@
612 add_executable(
613 remote_agent_test
614 remote_agent_test.cpp
615+
616+ ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.h
617+ ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.cpp
618 )
619
620 add_executable(
621
622=== modified file 'tests/dbus_test.cpp'
623--- tests/dbus_test.cpp 2014-08-04 08:32:57 +0000
624+++ tests/dbus_test.cpp 2016-01-04 15:02:54 +0000
625@@ -370,21 +370,19 @@
626 InvokeWithoutArgs(&state, &State::notify),
627 Return(core::trust::Request::Answer::denied)));
628
629- core::trust::dbus::AgentRegistry::Stub stub
630- {
631+ auto stub = core::trust::dbus::AgentRegistry::Stub::create(
632 core::trust::dbus::AgentRegistry::Stub::Configuration
633 {
634 agent_registry_object,
635 core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(),
636 service,
637 bus
638- }
639- };
640+ });
641
642 std::thread t{[bus]() { bus->run(); }};
643
644 // We register for the current user id.
645- stub.register_agent_for_user(core::trust::Uid{::getuid()}, agent);
646+ stub->register_agent_for_user(core::trust::Uid{::getuid()}, agent);
647
648 // Tell the other side that we are good to go.
649 agent_registered.try_signal_ready_for(std::chrono::milliseconds{500});
650@@ -393,7 +391,7 @@
651 state.wait();
652
653 // And unregister again.
654- stub.unregister_agent_for_user(core::trust::Uid{::getuid()});
655+ stub->unregister_agent_for_user(core::trust::Uid{::getuid()});
656
657 bus->stop();
658
659
660=== modified file 'tests/remote_agent_test.cpp'
661--- tests/remote_agent_test.cpp 2015-08-14 09:53:12 +0000
662+++ tests/remote_agent_test.cpp 2016-01-04 15:02:54 +0000
663@@ -30,6 +30,8 @@
664 #include <core/dbus/asio/executor.h>
665 #include <core/dbus/fixture.h>
666
667+#include <core/trust/runtime.h>
668+
669 #include <gmock/gmock.h>
670 #include <gtest/gtest.h>
671
672@@ -792,6 +794,12 @@
673 {
674 struct DBus : public core::dbus::testing::Fixture
675 {
676+ core::dbus::Bus::Ptr session_bus_with_executor()
677+ {
678+ auto sb = session_bus();
679+ sb->install_executor(core::trust::Runtime::instance().make_executor_for_bus(sb));
680+ return sb;
681+ }
682 };
683
684 std::string service_name
685@@ -804,10 +812,6 @@
686 {
687 using namespace ::testing;
688
689- core::testing::CrossProcessSync
690- stub_ready, // signals stub --| I'm ready |--> skeleton
691- skeleton_ready; // signals skeleton --| I'm ready |--> stub
692-
693 auto app = core::posix::fork([]()
694 {
695 while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500});
696@@ -825,7 +829,50 @@
697 const core::trust::Uid app_uid{::getuid()};
698 const core::trust::Pid app_pid{app.pid()};
699
700- auto stub = core::posix::fork([this, app_uid, app_pid, answer, &stub_ready, &skeleton_ready]()
701+ auto skeleton = core::posix::fork([this, answer]()
702+ {
703+ auto bus = session_bus_with_executor();
704+
705+ // We have to rely on a MockAgent to break the dependency on a running Mir instance.
706+ auto mock_agent = std::make_shared<::testing::NiceMock<MockAgent>>();
707+
708+ ON_CALL(*mock_agent, authenticate_request_with_parameters(_))
709+ .WillByDefault(Return(answer));
710+
711+ std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
712+
713+ auto service = core::dbus::Service::use_service(bus, dbus_service_name);
714+ auto object = service->object_for_path(core::dbus::types::ObjectPath
715+ {
716+ core::trust::remote::dbus::default_agent_registry_path
717+ });
718+
719+ core::dbus::DBus daemon{bus};
720+
721+ core::trust::remote::dbus::Agent::Skeleton::Configuration config
722+ {
723+ mock_agent,
724+ object,
725+ daemon.make_service_watcher(dbus_service_name),
726+ service,
727+ bus,
728+ core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
729+ };
730+
731+ auto skeleton = std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(std::move(config));
732+
733+ core::trust::Runtime::instance().run();
734+ return core::posix::exit::Status::success;
735+ }, core::posix::StandardStream::empty);
736+
737+
738+ // stubf models a trusted helper, with the following simplified
739+ // mode of operation:
740+ // (1.) Helper claims its unique name on the bus.
741+ // (2.) Helper installs an AgentRegistry::Skeleton.
742+ // (3.) Helper learns about per-user trust::Agent instances on the bus.
743+ // (4.) Helper issues requests for authentication.
744+ auto stubf = [this, app_uid, app_pid, answer]()
745 {
746 core::trust::Agent::RequestParameters ref_params
747 {
748@@ -836,10 +883,7 @@
749 "just an example description"
750 };
751
752- auto bus = session_bus();
753- bus->install_executor(core::dbus::asio::make_executor(bus));
754-
755- std::thread worker{[bus]() { bus->run(); }};
756+ auto bus = session_bus_with_executor();
757
758 std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
759
760@@ -857,76 +901,24 @@
761
762 auto stub = std::make_shared<core::trust::remote::dbus::Agent::Stub>(config);
763
764- stub_ready.try_signal_ready_for(std::chrono::milliseconds{1000});
765- skeleton_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000});
766+ std::this_thread::sleep_for(std::chrono::seconds(10));
767
768 for (unsigned int i = 0; i < 100; i++)
769 EXPECT_EQ(answer, stub->authenticate_request_with_parameters(ref_params));
770
771- bus->stop();
772-
773- if (worker.joinable())
774- worker.join();
775-
776 return Test::HasFailure() ?
777 core::posix::exit::Status::failure :
778 core::posix::exit::Status::success;
779- }, core::posix::StandardStream::empty);
780-
781- auto skeleton = core::posix::fork([this, answer, &stub_ready, &skeleton_ready]()
782- {
783- auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
784-
785- trap->signal_raised().connect([trap](core::posix::Signal)
786- {
787- trap->stop();
788- });
789-
790- auto bus = session_bus();
791- bus->install_executor(core::dbus::asio::make_executor(bus));
792-
793- std::thread worker{[bus]() { bus->run(); }};
794-
795- // We have to rely on a MockAgent to break the dependency on a running Mir instance.
796- auto mock_agent = std::make_shared<::testing::NiceMock<MockAgent>>();
797-
798- ON_CALL(*mock_agent, authenticate_request_with_parameters(_))
799- .WillByDefault(Return(answer));
800-
801- std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name;
802-
803- stub_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000});
804-
805- auto service = core::dbus::Service::use_service(bus, dbus_service_name);
806- auto object = service->object_for_path(core::dbus::types::ObjectPath
807- {
808- core::trust::remote::dbus::default_agent_registry_path
809- });
810-
811- core::trust::remote::dbus::Agent::Skeleton::Configuration config
812- {
813- mock_agent,
814- object,
815- service,
816- bus,
817- core::trust::remote::helpers::aa_get_task_con_app_id_resolver()
818- };
819-
820- auto skeleton = std::make_shared<core::trust::remote::dbus::Agent::Skeleton>(config);
821-
822- skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000});
823-
824- trap->run();
825-
826- bus->stop();
827-
828- if (worker.joinable())
829- worker.join();
830-
831- return core::posix::exit::Status::success;
832- }, core::posix::StandardStream::empty);
833-
834- EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
835+ };
836+
837+ std::this_thread::sleep_for(std::chrono::seconds(2));
838+ auto stub = core::posix::fork(stubf, core::posix::StandardStream::empty);
839+ EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
840+
841+ std::this_thread::sleep_for(std::chrono::seconds(2));
842+ stub = core::posix::fork(stubf, core::posix::StandardStream::empty);
843+ EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced)));
844+
845 skeleton.send_signal_or_throw(core::posix::Signal::sig_term);
846 EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced)));
847

Subscribers

People subscribed via source and target branches