Merge lp:~thomas-voss/location-service/add-standalone-provider-runner into lp:location-service/trunk
- add-standalone-provider-runner
- Merge into trunk
Proposed by
Thomas Voß
Status: | Merged |
---|---|
Approved by: | Manuel de la Peña |
Approved revision: | 114 |
Merged at revision: | 107 |
Proposed branch: | lp:~thomas-voss/location-service/add-standalone-provider-runner |
Merge into: | lp:location-service/trunk |
Prerequisite: | lp:~thomas-voss/location-service/expose-remote-provider-interface-as-part-of-dev-package |
Diff against target: |
1040 lines (+688/-58) 14 files modified
debian/ubuntu-location-service-bin.install (+1/-0) src/location_service/com/ubuntu/location/CMakeLists.txt (+37/-0) src/location_service/com/ubuntu/location/providers/remote/provider.cpp (+143/-37) src/location_service/com/ubuntu/location/providers/remote/provider.h (+4/-2) src/location_service/com/ubuntu/location/service/daemon.cpp (+2/-2) src/location_service/com/ubuntu/location/service/daemon.h (+1/-16) src/location_service/com/ubuntu/location/service/daemon_main.cpp (+1/-1) src/location_service/com/ubuntu/location/service/dbus_connection_factory.h (+52/-0) src/location_service/com/ubuntu/location/service/provider_daemon.cpp (+147/-0) src/location_service/com/ubuntu/location/service/provider_daemon.h (+69/-0) src/location_service/com/ubuntu/location/service/provider_daemon_main.cpp (+30/-0) tests/CMakeLists.txt (+3/-0) tests/remote_provider_test.cpp (+4/-0) tests/remote_providerd_test.cpp (+194/-0) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/add-standalone-provider-runner |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Manuel de la Peña (community) | Approve | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+234941@code.launchpad.net |
This proposal supersedes a proposal from 2014-09-17.
Commit message
Add a standalone daemon for executing providers out of process.
Description of the change
Add a standalone daemon for executing providers out of process.
To post a comment you must log in.
- 115. By Thomas Voß
-
Adjust copyright years.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Needs Fixing
(continuous-integration)
Revision history for this message
Manuel de la Peña (mandel) : | # |
review:
Approve
- 116. By Thomas Voß
-
Install provider daemon.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/ubuntu-location-service-bin.install' |
2 | --- debian/ubuntu-location-service-bin.install 2014-07-31 12:12:43 +0000 |
3 | +++ debian/ubuntu-location-service-bin.install 2014-09-17 13:26:40 +0000 |
4 | @@ -1,5 +1,6 @@ |
5 | etc/dbus-1/system.d/ |
6 | etc/init/* |
7 | usr/share/upstart/sessions/ubuntu-location-service-trust-stored.conf |
8 | +usr/bin/ubuntu-location-service-providerd |
9 | usr/bin/ubuntu-location-serviced |
10 | usr/bin/ubuntu-location-serviced-cli |
11 | |
12 | === modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt' |
13 | --- src/location_service/com/ubuntu/location/CMakeLists.txt 2014-09-17 13:26:40 +0000 |
14 | +++ src/location_service/com/ubuntu/location/CMakeLists.txt 2014-09-17 13:26:40 +0000 |
15 | @@ -131,12 +131,24 @@ |
16 | ) |
17 | |
18 | add_library( |
19 | + ubuntu-location-service-provider-daemon |
20 | + |
21 | + service/provider_daemon.cpp |
22 | +) |
23 | + |
24 | +add_library( |
25 | ubuntu-location-service-daemon |
26 | |
27 | service/daemon.cpp |
28 | ) |
29 | |
30 | add_executable( |
31 | + ubuntu-location-service-providerd |
32 | + |
33 | + service/provider_daemon_main.cpp |
34 | +) |
35 | + |
36 | +add_executable( |
37 | ubuntu-location-serviced |
38 | |
39 | service/daemon_main.cpp |
40 | @@ -149,12 +161,32 @@ |
41 | ) |
42 | |
43 | target_link_libraries( |
44 | + ubuntu-location-service-provider-daemon |
45 | + |
46 | + ubuntu-location-service |
47 | +) |
48 | + |
49 | +target_link_libraries( |
50 | ubuntu-location-service-daemon |
51 | |
52 | ubuntu-location-service |
53 | ) |
54 | |
55 | target_link_libraries( |
56 | + ubuntu-location-service-providerd |
57 | + |
58 | + ubuntu-location-service-provider-daemon |
59 | + |
60 | + ${ENABLED_PROVIDER_TARGETS} |
61 | + |
62 | + ${Boost_LIBRARIES} |
63 | + ${DBUS_LIBRARIES} |
64 | + ${DBUS_CPP_LIBRARIES} |
65 | + ${GLog_LIBRARY} |
66 | + ${GFlags_LIBRARY} |
67 | +) |
68 | + |
69 | +target_link_libraries( |
70 | ubuntu-location-serviced |
71 | |
72 | ubuntu-location-service-daemon |
73 | @@ -183,6 +215,11 @@ |
74 | ) |
75 | |
76 | install( |
77 | + TARGETS ubuntu-location-service-providerd |
78 | + DESTINATION ${CMAKE_INSTALL_BINDIR} |
79 | +) |
80 | + |
81 | +install( |
82 | TARGETS ubuntu-location-serviced |
83 | DESTINATION ${CMAKE_INSTALL_BINDIR} |
84 | ) |
85 | |
86 | === modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.cpp' |
87 | --- src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-09-17 13:26:40 +0000 |
88 | +++ src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-09-17 13:26:40 +0000 |
89 | @@ -26,6 +26,10 @@ |
90 | #include <core/dbus/signal.h> |
91 | #include <core/dbus/asio/executor.h> |
92 | |
93 | +#include <core/posix/this_process.h> |
94 | + |
95 | +#include <boost/asio.hpp> |
96 | + |
97 | #include <thread> |
98 | |
99 | namespace cul = com::ubuntu::location; |
100 | @@ -35,6 +39,73 @@ |
101 | |
102 | namespace |
103 | { |
104 | +struct Runtime |
105 | +{ |
106 | + static Runtime& instance() |
107 | + { |
108 | + static Runtime runtime; |
109 | + return runtime; |
110 | + } |
111 | + |
112 | + Runtime() |
113 | + : keep_alive{io_service}, |
114 | + worker1 |
115 | + { |
116 | + [this]() |
117 | + { |
118 | + io_service.run(); |
119 | + } |
120 | + }, |
121 | + worker2 |
122 | + { |
123 | + [this]() |
124 | + { |
125 | + io_service.run(); |
126 | + } |
127 | + } |
128 | + { |
129 | + } |
130 | + |
131 | + ~Runtime() |
132 | + { |
133 | + io_service.stop(); |
134 | + |
135 | + if (worker1.joinable()) |
136 | + worker1.join(); |
137 | + |
138 | + if (worker2.joinable()) |
139 | + worker2.join(); |
140 | + } |
141 | + |
142 | + boost::asio::io_service io_service; |
143 | + boost::asio::io_service::work keep_alive; |
144 | + std::thread worker1; |
145 | + std::thread worker2; |
146 | +}; |
147 | + |
148 | +core::dbus::Bus::Ptr bus_from_name(const std::string& bus_name) |
149 | +{ |
150 | + core::dbus::Bus::Ptr bus; |
151 | + |
152 | + if (bus_name == "system") |
153 | + bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::system); |
154 | + else if (bus_name == "session") |
155 | + bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); |
156 | + else if (bus_name == "system_with_address_from_env") |
157 | + bus = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SYSTEM_BUS_ADDRESS")); |
158 | + else if (bus_name == "session_with_address_from_env") |
159 | + bus = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS")); |
160 | + |
161 | + if (not bus) throw std::runtime_error |
162 | + { |
163 | + "Could not create bus for name: " + bus_name |
164 | + }; |
165 | + |
166 | + bus->install_executor(core::dbus::asio::make_executor(bus, Runtime::instance().io_service)); |
167 | + |
168 | + return bus; |
169 | +} |
170 | + |
171 | void throw_if_error(const dbus::Result<void>& result) |
172 | { |
173 | if (result.is_error()) throw std::runtime_error |
174 | @@ -52,13 +123,6 @@ |
175 | }; |
176 | return result.value(); |
177 | } |
178 | - |
179 | -dbus::Bus::Ptr the_system_bus() |
180 | -{ |
181 | - dbus::Bus::Ptr system_bus = std::make_shared<dbus::Bus>(dbus::WellKnownBus::system); |
182 | - system_bus->install_executor(core::dbus::asio::make_executor(system_bus)); |
183 | - return system_bus; |
184 | -} |
185 | } |
186 | |
187 | struct remote::Provider::Stub::Private |
188 | @@ -84,12 +148,14 @@ |
189 | |
190 | cul::Provider::Ptr remote::Provider::Stub::create_instance(const cul::ProviderFactory::Configuration& config) |
191 | { |
192 | + auto bus_name = config.count(Stub::key_bus) > 0 ? config.get<std::string>(Stub::key_bus) : |
193 | + "system"; |
194 | auto name = config.count(Stub::key_name) > 0 ? config.get<std::string>(Stub::key_name) : |
195 | throw std::runtime_error("Missing bus-name"); |
196 | auto path = config.count(Stub::key_path) > 0 ? config.get<std::string>(Stub::key_path) : |
197 | throw std::runtime_error("Missing bus-path"); |
198 | |
199 | - auto bus = the_system_bus(); |
200 | + auto bus = bus_from_name(bus_name); |
201 | auto service = dbus::Service::use_service(bus, name); |
202 | auto object = service->object_for_path(path); |
203 | |
204 | @@ -122,11 +188,12 @@ |
205 | |
206 | remote::Provider::Stub::~Stub() noexcept |
207 | { |
208 | + VLOG(10) << __PRETTY_FUNCTION__; |
209 | } |
210 | |
211 | bool remote::Provider::Stub::matches_criteria(const cul::Criteria& criteria) |
212 | { |
213 | - VLOG(10) << __PRETTY_FUNCTION__ << std::endl; |
214 | + VLOG(10) << __PRETTY_FUNCTION__ << std::endl; |
215 | return throw_if_error_or_return(d->stub.object->transact_method<remote::Interface::MatchesCriteria, bool>(criteria)); |
216 | } |
217 | |
218 | @@ -150,56 +217,108 @@ |
219 | |
220 | void remote::Provider::Stub::on_reference_location_updated(const cul::Update<cul::Position>& position) |
221 | { |
222 | - VLOG(10) << __PRETTY_FUNCTION__; |
223 | - throw_if_error(d->stub.object->transact_method<remote::Interface::OnReferenceLocationChanged, void>(position)); |
224 | + std::weak_ptr<Private> wp{d}; |
225 | + Runtime::instance().io_service.post([wp, position]() |
226 | + { |
227 | + auto sp = wp.lock(); |
228 | + |
229 | + if (not sp) |
230 | + return; |
231 | + |
232 | + try |
233 | + { |
234 | + throw_if_error(sp->stub.object->transact_method<remote::Interface::OnReferenceLocationChanged, void>(position)); |
235 | + } catch(const std::exception& e) |
236 | + { |
237 | + // We drop the error and just log it for post-mortem inspection. |
238 | + LOG(WARNING) << "Transaction<remote::Interface::OnReferenceLocationChanged>: " << e.what(); |
239 | + } |
240 | + }); |
241 | } |
242 | |
243 | void remote::Provider::Stub::on_reference_velocity_updated(const cul::Update<cul::Velocity>& velocity) |
244 | { |
245 | - VLOG(10) << __PRETTY_FUNCTION__; |
246 | - throw_if_error(d->stub.object->transact_method<remote::Interface::OnReferenceVelocityChanged, void>(velocity)); |
247 | + std::weak_ptr<Private> wp{d}; |
248 | + Runtime::instance().io_service.post([wp, velocity]() |
249 | + { |
250 | + auto sp = wp.lock(); |
251 | + |
252 | + if (not sp) |
253 | + return; |
254 | + |
255 | + try |
256 | + { |
257 | + throw_if_error(sp->stub.object->transact_method<remote::Interface::OnReferenceVelocityChanged, void>(velocity)); |
258 | + } catch(const std::exception& e) |
259 | + { |
260 | + // We drop the error and just log it for post-mortem inspection. |
261 | + LOG(WARNING) << "Transaction<remote::Interface::OnReferenceVelocityChanged>: " << e.what(); |
262 | + } |
263 | + }); |
264 | } |
265 | |
266 | void remote::Provider::Stub::on_reference_heading_updated(const cul::Update<cul::Heading>& heading) |
267 | { |
268 | - VLOG(10) << __PRETTY_FUNCTION__; |
269 | - throw_if_error(d->stub.object->transact_method<remote::Interface::OnReferenceHeadingChanged, void>(heading)); |
270 | + std::weak_ptr<Private> wp{d}; |
271 | + Runtime::instance().io_service.post([wp, heading]() |
272 | + { |
273 | + auto sp = wp.lock(); |
274 | + |
275 | + if (not sp) |
276 | + return; |
277 | + |
278 | + try |
279 | + { |
280 | + throw_if_error(sp->stub.object->transact_method<remote::Interface::OnReferenceHeadingChanged, void>(heading)); |
281 | + } catch(const std::exception& e) |
282 | + { |
283 | + // We drop the error and just log it for post-mortem inspection. |
284 | + LOG(WARNING) << "Transaction<remote::Interface::OnReferenceHeadingChanged>: " << e.what(); |
285 | + } |
286 | + }); |
287 | } |
288 | |
289 | void remote::Provider::Stub::start_position_updates() |
290 | { |
291 | - VLOG(10) << __PRETTY_FUNCTION__; |
292 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
293 | throw_if_error(d->stub.object->transact_method<remote::Interface::StartPositionUpdates, void>()); |
294 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
295 | } |
296 | |
297 | void remote::Provider::Stub::stop_position_updates() |
298 | { |
299 | - VLOG(10) << __PRETTY_FUNCTION__; |
300 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
301 | throw_if_error(d->stub.object->transact_method<remote::Interface::StopPositionUpdates, void>()); |
302 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
303 | } |
304 | |
305 | void remote::Provider::Stub::start_heading_updates() |
306 | { |
307 | - VLOG(10) << __PRETTY_FUNCTION__; |
308 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
309 | throw_if_error(d->stub.object->transact_method<remote::Interface::StartHeadingUpdates, void>()); |
310 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
311 | } |
312 | |
313 | void remote::Provider::Stub::stop_heading_updates() |
314 | { |
315 | - VLOG(10) << __PRETTY_FUNCTION__; |
316 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
317 | throw_if_error(d->stub.object->transact_method<remote::Interface::StopHeadingUpdates, void>()); |
318 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
319 | } |
320 | |
321 | void remote::Provider::Stub::start_velocity_updates() |
322 | { |
323 | - VLOG(10) << __PRETTY_FUNCTION__; |
324 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
325 | throw_if_error(d->stub.object->transact_method<remote::Interface::StartVelocityUpdates, void>()); |
326 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
327 | + |
328 | } |
329 | |
330 | void remote::Provider::Stub::stop_velocity_updates() |
331 | { |
332 | - VLOG(10) << __PRETTY_FUNCTION__; |
333 | + VLOG(10) << "> " << __PRETTY_FUNCTION__; |
334 | throw_if_error(d->stub.object->transact_method<remote::Interface::StopVelocityUpdates, void>()); |
335 | + VLOG(10) << "< " << __PRETTY_FUNCTION__; |
336 | } |
337 | |
338 | struct remote::Provider::Skeleton::Private |
339 | @@ -212,14 +331,17 @@ |
340 | { |
341 | impl->updates().position.connect([this](const cul::Update<cul::Position>& position) |
342 | { |
343 | + VLOG(100) << "Position changed reported by impl: " << position; |
344 | skeleton.signals.position_changed->emit(position.value); |
345 | }), |
346 | impl->updates().heading.connect([this](const cul::Update<cul::Heading>& heading) |
347 | { |
348 | + VLOG(100) << "Heading changed reported by impl: " << heading; |
349 | skeleton.signals.heading_changed->emit(heading.value); |
350 | }), |
351 | impl->updates().velocity.connect([this](const cul::Update<cul::Velocity>& velocity) |
352 | { |
353 | + VLOG(100) << "Velocity changed reported by impl: " << velocity; |
354 | skeleton.signals.velocity_changed->emit(velocity.value); |
355 | }) |
356 | } |
357 | @@ -243,22 +365,6 @@ |
358 | : cul::Provider(), |
359 | d(new Private(config)) |
360 | { |
361 | - // Wire up to updates. |
362 | - d->impl->updates().position.connect([this](const cul::Update<cul::Position>& position) |
363 | - { |
364 | - d->skeleton.signals.position_changed->emit(position.value); |
365 | - }); |
366 | - |
367 | - d->impl->updates().heading.connect([this](const cul::Update<cul::Heading>& heading) |
368 | - { |
369 | - d->skeleton.signals.heading_changed->emit(heading.value); |
370 | - }); |
371 | - |
372 | - d->impl->updates().velocity.connect([this](const cul::Update<cul::Velocity>& velocity) |
373 | - { |
374 | - d->skeleton.signals.velocity_changed->emit(velocity.value); |
375 | - }); |
376 | - |
377 | // And install method handlers. |
378 | d->skeleton.object->install_method_handler<remote::Interface::MatchesCriteria>([this](const dbus::Message::Ptr & msg) |
379 | { |
380 | |
381 | === modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.h' |
382 | --- src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-09-17 13:26:40 +0000 |
383 | +++ src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-09-17 13:26:40 +0000 |
384 | @@ -48,6 +48,8 @@ |
385 | // from the provided property bundle. |
386 | static Provider::Ptr create_instance(const ProviderFactory::Configuration&); |
387 | |
388 | + // Name of the command line parameter for passing in the DBus to connect to. |
389 | + static constexpr const char* key_bus{"bus"}; |
390 | // Name of the command line parameter for passing in the remote service name. |
391 | static constexpr const char* key_name{"name"}; |
392 | // Name of the command line parameter for passing in the path of the remote provider impl. |
393 | @@ -76,7 +78,7 @@ |
394 | |
395 | private: |
396 | struct Private; |
397 | - std::unique_ptr<Private> d; |
398 | + std::shared_ptr<Private> d; |
399 | }; |
400 | |
401 | class Skeleton : public com::ubuntu::location::Provider |
402 | @@ -106,7 +108,7 @@ |
403 | |
404 | private: |
405 | struct Private; |
406 | - std::unique_ptr<Private> d; |
407 | + std::shared_ptr<Private> d; |
408 | }; |
409 | }; |
410 | } |
411 | |
412 | === modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp' |
413 | --- src/location_service/com/ubuntu/location/service/daemon.cpp 2014-08-13 13:08:22 +0000 |
414 | +++ src/location_service/com/ubuntu/location/service/daemon.cpp 2014-09-17 13:26:40 +0000 |
415 | @@ -89,7 +89,7 @@ |
416 | location::service::Daemon::Configuration location::service::Daemon::Configuration::from_command_line_args( |
417 | int argc, |
418 | const char** argv, |
419 | - location::service::Daemon::DBusConnectionFactory factory) |
420 | + location::service::DBusConnectionFactory factory) |
421 | { |
422 | location::service::Daemon::Configuration result; |
423 | |
424 | @@ -289,7 +289,7 @@ |
425 | location::service::Daemon::Cli::Configuration location::service::Daemon::Cli::Configuration::from_command_line_args( |
426 | int argc, |
427 | const char** argv, |
428 | - location::service::Daemon::DBusConnectionFactory factory) |
429 | + location::service::DBusConnectionFactory factory) |
430 | { |
431 | location::service::Daemon::Cli::Configuration result; |
432 | |
433 | |
434 | === modified file 'src/location_service/com/ubuntu/location/service/daemon.h' |
435 | --- src/location_service/com/ubuntu/location/service/daemon.h 2014-07-29 10:51:48 +0000 |
436 | +++ src/location_service/com/ubuntu/location/service/daemon.h 2014-09-17 13:26:40 +0000 |
437 | @@ -20,7 +20,7 @@ |
438 | |
439 | #include <com/ubuntu/location/configuration.h> |
440 | |
441 | -#include <core/dbus/bus.h> |
442 | +#include <com/ubuntu/location/service/dbus_connection_factory.h> |
443 | |
444 | #include <iosfwd> |
445 | #include <string> |
446 | @@ -38,21 +38,6 @@ |
447 | */ |
448 | struct Daemon |
449 | { |
450 | - /** @brief Function signature for creating DBus connections. */ |
451 | - typedef std::function<core::dbus::Bus::Ptr(core::dbus::WellKnownBus)> DBusConnectionFactory; |
452 | - |
453 | - /** @brief Returns the default connection factory. */ |
454 | - static DBusConnectionFactory default_dbus_connection_factory() |
455 | - { |
456 | - return [](core::dbus::WellKnownBus bus) |
457 | - { |
458 | - return core::dbus::Bus::Ptr |
459 | - { |
460 | - new core::dbus::Bus(bus) |
461 | - }; |
462 | - }; |
463 | - } |
464 | - |
465 | /** @brief Describes the command-line interface to the daemon. */ |
466 | struct Cli |
467 | { |
468 | |
469 | === modified file 'src/location_service/com/ubuntu/location/service/daemon_main.cpp' |
470 | --- src/location_service/com/ubuntu/location/service/daemon_main.cpp 2014-08-14 20:25:22 +0000 |
471 | +++ src/location_service/com/ubuntu/location/service/daemon_main.cpp 2014-09-17 13:26:40 +0000 |
472 | @@ -44,7 +44,7 @@ |
473 | { |
474 | FLAGS_logtostderr = true; |
475 | VLOG(1) << "Problem creating directory for log files: " << ec << "." |
476 | - << "Falling back to stderr logging."; |
477 | + << "Falling back to stderr logging."; |
478 | } |
479 | |
480 | FLAGS_log_dir = log_dir; |
481 | |
482 | === added file 'src/location_service/com/ubuntu/location/service/dbus_connection_factory.h' |
483 | --- src/location_service/com/ubuntu/location/service/dbus_connection_factory.h 1970-01-01 00:00:00 +0000 |
484 | +++ src/location_service/com/ubuntu/location/service/dbus_connection_factory.h 2014-09-17 13:26:40 +0000 |
485 | @@ -0,0 +1,52 @@ |
486 | +/* |
487 | + * Copyright © 2012-2013 Canonical Ltd. |
488 | + * |
489 | + * This program is free software: you can redistribute it and/or modify it |
490 | + * under the terms of the GNU Lesser General Public License version 3, |
491 | + * as published by the Free Software Foundation. |
492 | + * |
493 | + * This program is distributed in the hope that it will be useful, |
494 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
495 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
496 | + * GNU Lesser General Public License for more details. |
497 | + * |
498 | + * You should have received a copy of the GNU Lesser General Public License |
499 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
500 | + * |
501 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
502 | + */ |
503 | +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DBUS_CONNECTION_FACTORY_H_ |
504 | +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DBUS_CONNECTION_FACTORY_H_ |
505 | + |
506 | +#include <core/dbus/bus.h> |
507 | + |
508 | +#include <functional> |
509 | + |
510 | +namespace com |
511 | +{ |
512 | +namespace ubuntu |
513 | +{ |
514 | +namespace location |
515 | +{ |
516 | +namespace service |
517 | +{ |
518 | +/** @brief Function signature for creating DBus connections. */ |
519 | +typedef std::function<core::dbus::Bus::Ptr(core::dbus::WellKnownBus)> DBusConnectionFactory; |
520 | + |
521 | +/** @brief Returns the default connection factory. */ |
522 | +static DBusConnectionFactory default_dbus_connection_factory() |
523 | +{ |
524 | + return [](core::dbus::WellKnownBus bus) |
525 | + { |
526 | + return core::dbus::Bus::Ptr |
527 | + { |
528 | + new core::dbus::Bus(bus) |
529 | + }; |
530 | + }; |
531 | +} |
532 | +} |
533 | +} |
534 | +} |
535 | +} |
536 | + |
537 | +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_DBUS_CONNECTION_FACTORY_H_ |
538 | |
539 | === added file 'src/location_service/com/ubuntu/location/service/provider_daemon.cpp' |
540 | --- src/location_service/com/ubuntu/location/service/provider_daemon.cpp 1970-01-01 00:00:00 +0000 |
541 | +++ src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2014-09-17 13:26:40 +0000 |
542 | @@ -0,0 +1,147 @@ |
543 | +/* |
544 | + * Copyright © 2014 Canonical Ltd. |
545 | + * |
546 | + * This program is free software: you can redistribute it and/or modify it |
547 | + * under the terms of the GNU Lesser General Public License version 3, |
548 | + * as published by the Free Software Foundation. |
549 | + * |
550 | + * This program is distributed in the hope that it will be useful, |
551 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
552 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
553 | + * GNU Lesser General Public License for more details. |
554 | + * |
555 | + * You should have received a copy of the GNU Lesser General Public License |
556 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
557 | + * |
558 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
559 | + */ |
560 | + |
561 | +#include <com/ubuntu/location/service/provider_daemon.h> |
562 | + |
563 | +#include <com/ubuntu/location/configuration.h> |
564 | +#include <com/ubuntu/location/provider_factory.h> |
565 | + |
566 | +#include <com/ubuntu/location/providers/remote/skeleton.h> |
567 | + |
568 | +#include <com/ubuntu/location/service/configuration.h> |
569 | +#include <com/ubuntu/location/service/program_options.h> |
570 | + |
571 | +#include <core/posix/signal.h> |
572 | + |
573 | +namespace location = com::ubuntu::location; |
574 | + |
575 | +namespace |
576 | +{ |
577 | +location::ProgramOptions init_daemon_options() |
578 | +{ |
579 | + location::ProgramOptions options; |
580 | + |
581 | + options.add("help", "Produces this help message"); |
582 | + options.add<std::string>("service-name", |
583 | + "The name of the service under which the provider should be exposed."); |
584 | + options.add<std::string>("service-path", |
585 | + "The dbus object path under which the provider is known."); |
586 | + options.add<std::string>("provider", |
587 | + "The provider that should be exposed to the bus"); |
588 | + |
589 | + return options; |
590 | +} |
591 | + |
592 | +location::ProgramOptions& mutable_daemon_options() |
593 | +{ |
594 | + static location::ProgramOptions options = init_daemon_options(); |
595 | + return options; |
596 | +} |
597 | +} |
598 | + |
599 | +location::service::ProviderDaemon::Configuration location::service::ProviderDaemon::Configuration::from_command_line_args( |
600 | + int argc, const char** argv, location::service::DBusConnectionFactory factory) |
601 | +{ |
602 | + if (!mutable_daemon_options().parse_from_command_line_args(argc, argv)) |
603 | + throw std::runtime_error{"Could not parse command-line, aborting..."}; |
604 | + |
605 | + location::service::ProviderDaemon::Configuration result; |
606 | + |
607 | + result.connection = factory(mutable_daemon_options().bus()); |
608 | + |
609 | + auto service = core::dbus::Service::add_service( |
610 | + result.connection, |
611 | + mutable_daemon_options().value_for_key<std::string>("service-name")); |
612 | + |
613 | + result.object = service->add_object_for_path(core::dbus::types::ObjectPath |
614 | + { |
615 | + mutable_daemon_options().value_for_key<std::string>("service-path") |
616 | + }); |
617 | + |
618 | + auto provider_name = mutable_daemon_options().value_for_key<std::string>("provider"); |
619 | + location::Configuration config; |
620 | + |
621 | + mutable_daemon_options().enumerate_unrecognized_options([&config, provider_name](const std::string& s) |
622 | + { |
623 | + std::stringstream in(s); |
624 | + std::string key, value; |
625 | + |
626 | + std::getline(in, key, '='); |
627 | + std::getline(in, value, '='); |
628 | + |
629 | + std::size_t pos = key.find(provider_name); |
630 | + if (pos == std::string::npos) |
631 | + return; |
632 | + |
633 | + static const std::string option_marker{"--"}; |
634 | + static const std::string scope_separator{"::"}; |
635 | + |
636 | + key = key.erase(key.find_first_of(option_marker), option_marker.size()); |
637 | + key = key.erase(key.find_first_of(provider_name), provider_name.size()); |
638 | + key = key.erase(key.find_first_of(scope_separator), scope_separator.size()); |
639 | + |
640 | + config.put(key, value); |
641 | + }); |
642 | + |
643 | + result.provider = location::ProviderFactory::instance().create_provider_for_name_with_config( |
644 | + provider_name, |
645 | + config); |
646 | + |
647 | + return result; |
648 | +} |
649 | + |
650 | +int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& configuration) |
651 | +{ |
652 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
653 | + { |
654 | + core::posix::Signal::sig_term, |
655 | + core::posix::Signal::sig_int |
656 | + }); |
657 | + |
658 | + trap->signal_raised().connect([trap](const core::posix::Signal&) |
659 | + { |
660 | + trap->stop(); |
661 | + }); |
662 | + |
663 | + std::thread worker |
664 | + { |
665 | + [configuration]() |
666 | + { |
667 | + configuration.connection->run(); |
668 | + } |
669 | + }; |
670 | + |
671 | + auto skeleton = location::providers::remote::skeleton::create_with_configuration(location::providers::remote::skeleton::Configuration |
672 | + { |
673 | + configuration.object, |
674 | + configuration.connection, |
675 | + configuration.provider |
676 | + }); |
677 | + |
678 | + |
679 | + std::cout << "We are up and running" << std::endl; |
680 | + |
681 | + trap->run(); |
682 | + |
683 | + configuration.connection->stop(); |
684 | + |
685 | + if (worker.joinable()) |
686 | + worker.join(); |
687 | + |
688 | + return EXIT_SUCCESS; |
689 | +} |
690 | |
691 | === added file 'src/location_service/com/ubuntu/location/service/provider_daemon.h' |
692 | --- src/location_service/com/ubuntu/location/service/provider_daemon.h 1970-01-01 00:00:00 +0000 |
693 | +++ src/location_service/com/ubuntu/location/service/provider_daemon.h 2014-09-17 13:26:40 +0000 |
694 | @@ -0,0 +1,69 @@ |
695 | +/* |
696 | + * Copyright © 2014 Canonical Ltd. |
697 | + * |
698 | + * This program is free software: you can redistribute it and/or modify it |
699 | + * under the terms of the GNU Lesser General Public License version 3, |
700 | + * as published by the Free Software Foundation. |
701 | + * |
702 | + * This program is distributed in the hope that it will be useful, |
703 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
704 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
705 | + * GNU Lesser General Public License for more details. |
706 | + * |
707 | + * You should have received a copy of the GNU Lesser General Public License |
708 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
709 | + * |
710 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
711 | + */ |
712 | +#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_PROVIDER_DAEMON_H_ |
713 | +#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_PROVIDER_DAEMON_H_ |
714 | + |
715 | +#include <com/ubuntu/location/provider.h> |
716 | + |
717 | +#include <com/ubuntu/location/service/dbus_connection_factory.h> |
718 | + |
719 | +#include <core/dbus/bus.h> |
720 | +#include <core/dbus/object.h> |
721 | + |
722 | +namespace com |
723 | +{ |
724 | +namespace ubuntu |
725 | +{ |
726 | +namespace location |
727 | +{ |
728 | +namespace service |
729 | +{ |
730 | +// Provides a default out-of-process runner for known providers, |
731 | +// leveraging the actual provider instance and a remote::Provider to |
732 | +// expose it to the bus. |
733 | +struct ProviderDaemon |
734 | +{ |
735 | + // Startup configuration goes here. |
736 | + struct Configuration |
737 | + { |
738 | + // Initializes a startup configuration from a command line. |
739 | + // Throws in case of issues. |
740 | + // Known parameters are: |
741 | + // --bus={system, session}: The bus to connect to. |
742 | + // --service-name=name: The name of the service under which the provider should be exposed. |
743 | + // --service-path=path: The dbus object path under which the provider is known. |
744 | + // --provider=name: The name of the actual provider implementation. |
745 | + static Configuration from_command_line_args(int argc, const char** argv, DBusConnectionFactory factory); |
746 | + |
747 | + // The bus connection that should be used by the remote::Provider::Skeleton instance. |
748 | + core::dbus::Bus::Ptr connection; |
749 | + // The object on the bus that represents the remote::Provider::Skeleton. |
750 | + core::dbus::Object::Ptr object; |
751 | + // The actual provider implementation. |
752 | + Provider::Ptr provider; |
753 | + }; |
754 | + |
755 | + // Executes the daemon with the given configuration. |
756 | + static int main(const Configuration& configuration); |
757 | +}; |
758 | +} |
759 | +} |
760 | +} |
761 | +} |
762 | + |
763 | +#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_SERVICE_PROVIDER_DAEMON_H_ |
764 | |
765 | === added file 'src/location_service/com/ubuntu/location/service/provider_daemon_main.cpp' |
766 | --- src/location_service/com/ubuntu/location/service/provider_daemon_main.cpp 1970-01-01 00:00:00 +0000 |
767 | +++ src/location_service/com/ubuntu/location/service/provider_daemon_main.cpp 2014-09-17 13:26:40 +0000 |
768 | @@ -0,0 +1,30 @@ |
769 | +/* |
770 | + * Copyright © 2014 Canonical Ltd. |
771 | + * |
772 | + * This program is free software: you can redistribute it and/or modify it |
773 | + * under the terms of the GNU Lesser General Public License version 3, |
774 | + * as published by the Free Software Foundation. |
775 | + * |
776 | + * This program is distributed in the hope that it will be useful, |
777 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
778 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
779 | + * GNU Lesser General Public License for more details. |
780 | + * |
781 | + * You should have received a copy of the GNU Lesser General Public License |
782 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
783 | + * |
784 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
785 | + */ |
786 | + |
787 | +#include <com/ubuntu/location/service/provider_daemon.h> |
788 | + |
789 | +namespace location = com::ubuntu::location; |
790 | + |
791 | +int main(int argc, const char** argv) |
792 | +{ |
793 | + return location::service::ProviderDaemon::main( |
794 | + location::service::ProviderDaemon::Configuration::from_command_line_args( |
795 | + argc, |
796 | + argv, |
797 | + location::service::default_dbus_connection_factory())); |
798 | +} |
799 | |
800 | === modified file 'tests/CMakeLists.txt' |
801 | --- tests/CMakeLists.txt 2014-09-17 13:26:40 +0000 |
802 | +++ tests/CMakeLists.txt 2014-09-17 13:26:40 +0000 |
803 | @@ -37,6 +37,7 @@ |
804 | |
805 | ubuntu-location-service |
806 | ubuntu-location-service-connectivity |
807 | + ubuntu-location-service-provider-daemon |
808 | ubuntu-location-service-daemon |
809 | |
810 | mongoose |
811 | @@ -117,5 +118,7 @@ |
812 | endif (LOCATION_SERVICE_ENABLE_DBUS_TEST_RUNNER) |
813 | endif (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDERS) |
814 | |
815 | +LOCATION_SERVICE_ADD_TEST(remote_providerd_test remote_providerd_test.cpp) |
816 | + |
817 | LOCATION_SERVICE_ADD_TEST(remote_provider_test remote_provider_test.cpp) |
818 | LOCATION_SERVICE_ADD_TEST(espoo_provider_test espoo_provider_test.cpp) |
819 | |
820 | === modified file 'tests/remote_provider_test.cpp' |
821 | --- tests/remote_provider_test.cpp 2014-09-17 13:26:40 +0000 |
822 | +++ tests/remote_provider_test.cpp 2014-09-17 13:26:40 +0000 |
823 | @@ -388,6 +388,8 @@ |
824 | |
825 | bus->stop(); |
826 | |
827 | + std::cout << "Stopped the bus" << std::endl; |
828 | + |
829 | if (worker.joinable()) |
830 | worker.join(); |
831 | |
832 | @@ -395,7 +397,9 @@ |
833 | core::posix::exit::Status::success; |
834 | }, core::posix::StandardStream::empty); |
835 | |
836 | + std::cout << "Waiting for stub to finish." << std::endl; |
837 | EXPECT_TRUE(did_finish_successfully(stub.wait_for(core::posix::wait::Flags::untraced))); |
838 | + std::cout << "Shutting down skeleton." << std::endl; |
839 | skeleton.send_signal_or_throw(core::posix::Signal::sig_term); |
840 | EXPECT_TRUE(did_finish_successfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); |
841 | } |
842 | |
843 | === added file 'tests/remote_providerd_test.cpp' |
844 | --- tests/remote_providerd_test.cpp 1970-01-01 00:00:00 +0000 |
845 | +++ tests/remote_providerd_test.cpp 2014-09-17 13:26:40 +0000 |
846 | @@ -0,0 +1,194 @@ |
847 | +/* |
848 | + * Copyright © 2014 Canonical Ltd. |
849 | + * |
850 | + * This program is free software: you can redistribute it and/or modify it |
851 | + * under the terms of the GNU Lesser General Public License version 3, |
852 | + * as published by the Free Software Foundation. |
853 | + * |
854 | + * This program is distributed in the hope that it will be useful, |
855 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
856 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
857 | + * GNU Lesser General Public License for more details. |
858 | + * |
859 | + * You should have received a copy of the GNU Lesser General Public License |
860 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
861 | + * |
862 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
863 | + */ |
864 | + |
865 | +#include <com/ubuntu/location/service/daemon.h> |
866 | +#include <com/ubuntu/location/service/provider_daemon.h> |
867 | + |
868 | +#include <com/ubuntu/location/service/stub.h> |
869 | + |
870 | +#include <com/ubuntu/location/position.h> |
871 | +#include <com/ubuntu/location/update.h> |
872 | + |
873 | +#include <core/dbus/fixture.h> |
874 | + |
875 | +#include <core/dbus/asio/executor.h> |
876 | + |
877 | +#include <core/posix/fork.h> |
878 | + |
879 | +#include <gmock/gmock.h> |
880 | + |
881 | +namespace location = com::ubuntu::location; |
882 | + |
883 | +namespace |
884 | +{ |
885 | +::testing::AssertionResult did_finish_successfully(const core::posix::wait::Result& result) |
886 | +{ |
887 | + if (result.status != core::posix::wait::Result::Status::exited) |
888 | + return ::testing::AssertionFailure() << "Process did not exit, but: " << (int)result.status; |
889 | + if (result.detail.if_exited.status != core::posix::exit::Status::success) |
890 | + return ::testing::AssertionFailure() << "Process did exit with failure."; |
891 | + |
892 | + return ::testing::AssertionSuccess(); |
893 | +} |
894 | + |
895 | +struct MockEventReceiver |
896 | +{ |
897 | + MOCK_METHOD1(position_update_received, void(const location::Update<location::Position>&)); |
898 | + MOCK_METHOD1(heading_update_received, void(const location::Update<location::Heading>&)); |
899 | + MOCK_METHOD1(velocity_update_received, void(const location::Update<location::Velocity>&)); |
900 | +}; |
901 | + |
902 | +struct RemoteProviderdTest : public core::dbus::testing::Fixture |
903 | +{ |
904 | + |
905 | +}; |
906 | +} |
907 | + |
908 | +TEST_F(RemoteProviderdTest, AClientReceivesUpdatesFromAnOutOfProcessProvider) |
909 | +{ |
910 | + auto oopp = core::posix::fork([this]() |
911 | + { |
912 | + auto bus = session_bus(); |
913 | + bus->install_executor(core::dbus::asio::make_executor(bus)); |
914 | + |
915 | + const char* argv[] = |
916 | + { |
917 | + "--bus", "session", // 2 |
918 | + "--service-name", "com.ubuntu.location.providers.Dummy", // 4 |
919 | + "--service-path", "/com/ubuntu/location/providers/Dummy", // 6 |
920 | + "--provider", "dummy::Provider" // 8 |
921 | + }; |
922 | + |
923 | + auto dbus_connection_factory = [bus](core::dbus::WellKnownBus) |
924 | + { |
925 | + return bus; |
926 | + }; |
927 | + |
928 | + return static_cast<core::posix::exit::Status>( |
929 | + location::service::ProviderDaemon::main( |
930 | + location::service::ProviderDaemon::Configuration::from_command_line_args( |
931 | + 8, argv, dbus_connection_factory))); |
932 | + }, core::posix::StandardStream::empty); |
933 | + |
934 | + std::this_thread::sleep_for(std::chrono::milliseconds{250}); |
935 | + |
936 | + auto service = core::posix::fork([this]() |
937 | + { |
938 | + core::posix::this_process::env::set_or_throw( |
939 | + "TRUST_STORE_PERMISSION_MANAGER_IS_RUNNING_UNDER_TESTING", |
940 | + "1"); |
941 | + |
942 | + const char* argv[] = |
943 | + { |
944 | + "--bus", "session", // 2 |
945 | + "--provider", "remote::Provider", // 4 |
946 | + "--remote::Provider::bus=session_with_address_from_env", // 5 |
947 | + "--remote::Provider::name=com.ubuntu.location.providers.Dummy", // 6 |
948 | + "--remote::Provider::path=/com/ubuntu/location/providers/Dummy" // 7 |
949 | + }; |
950 | + |
951 | + // The daemon instance requires two bus instances. |
952 | + auto dbus_connection_factory = [this](core::dbus::WellKnownBus) |
953 | + { |
954 | + return session_bus(); |
955 | + }; |
956 | + |
957 | + return static_cast<core::posix::exit::Status>( |
958 | + location::service::Daemon::main( |
959 | + location::service::Daemon::Configuration::from_command_line_args( |
960 | + 7, argv, dbus_connection_factory))); |
961 | + }, core::posix::StandardStream::empty); |
962 | + |
963 | + std::this_thread::sleep_for(std::chrono::milliseconds{250}); |
964 | + |
965 | + auto client = core::posix::fork([this]() |
966 | + { |
967 | + using namespace ::testing; |
968 | + |
969 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
970 | + { |
971 | + core::posix::Signal::sig_term, |
972 | + core::posix::Signal::sig_int |
973 | + }); |
974 | + |
975 | + trap->signal_raised().connect([trap](const core::posix::Signal&) |
976 | + { |
977 | + trap->stop(); |
978 | + }); |
979 | + |
980 | + auto bus = session_bus(); |
981 | + bus->install_executor(core::dbus::asio::make_executor(bus)); |
982 | + |
983 | + std::thread worker |
984 | + { |
985 | + [bus]() { bus->run(); } |
986 | + }; |
987 | + |
988 | + MockEventReceiver receiver; |
989 | + EXPECT_CALL(receiver, position_update_received(_)).Times(AtLeast(1)); |
990 | + EXPECT_CALL(receiver, heading_update_received(_)).Times(AtLeast(1)); |
991 | + EXPECT_CALL(receiver, velocity_update_received(_)).Times(AtLeast(1)); |
992 | + |
993 | + com::ubuntu::location::service::Stub service{bus}; |
994 | + |
995 | + auto session = service.create_session_for_criteria(location::Criteria{}); |
996 | + |
997 | + session->updates().position.changed().connect([&receiver](location::Update<location::Position> pos) |
998 | + { |
999 | + receiver.position_update_received(pos); |
1000 | + }); |
1001 | + |
1002 | + session->updates().heading.changed().connect([&receiver](location::Update<location::Heading> heading) |
1003 | + { |
1004 | + receiver.heading_update_received(heading); |
1005 | + }); |
1006 | + |
1007 | + session->updates().velocity.changed().connect([&receiver](location::Update<location::Velocity> velocity) |
1008 | + { |
1009 | + receiver.velocity_update_received(velocity); |
1010 | + }); |
1011 | + |
1012 | + session->updates().position_status = location::service::session::Interface::Updates::Status::enabled; |
1013 | + session->updates().velocity_status = location::service::session::Interface::Updates::Status::enabled; |
1014 | + session->updates().heading_status = location::service::session::Interface::Updates::Status::enabled; |
1015 | + |
1016 | + trap->run(); |
1017 | + |
1018 | + bus->stop(); |
1019 | + |
1020 | + if (worker.joinable()) |
1021 | + worker.join(); |
1022 | + |
1023 | + return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : |
1024 | + core::posix::exit::Status::success; |
1025 | + }, core::posix::StandardStream::empty); |
1026 | + |
1027 | + std::this_thread::sleep_for(std::chrono::milliseconds{4000}); |
1028 | + |
1029 | + std::cout << "Shutting down client" << std::endl; |
1030 | + client.send_signal_or_throw(core::posix::Signal::sig_term); |
1031 | + EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced))); |
1032 | + |
1033 | + std::cout << "Shutting down service" << std::endl; |
1034 | + service.send_signal_or_throw(core::posix::Signal::sig_term); |
1035 | + EXPECT_TRUE(did_finish_successfully(service.wait_for(core::posix::wait::Flags::untraced))); |
1036 | + |
1037 | + std::cout << "Shutting down oopp" << std::endl; |
1038 | + oopp.send_signal_or_throw(core::posix::Signal::sig_term); |
1039 | + EXPECT_TRUE(did_finish_successfully(oopp.wait_for(core::posix::wait::Flags::untraced))); |
1040 | +} |
FAILED: Continuous integration, rev:114 /code.launchpad .net/~thomas- voss/location- service/ add-standalone- provider- runner/ +merge/ 234941/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ location- service- ci/286/ jenkins. qa.ubuntu. com/job/ location- service- utopic- amd64-ci/ 193/console jenkins. qa.ubuntu. com/job/ location- service- utopic- armhf-ci/ 193/console jenkins. qa.ubuntu. com/job/ location- service- utopic- i386-ci/ 193/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/location- service- ci/286/ rebuild
http://