Merge lp:~pete-woods/ubuntu-app-launch/port-some-c-to-cpp into lp:ubuntu-app-launch
- port-some-c-to-cpp
- Merge into trunk.17.04
Status: | Needs review |
---|---|
Proposed branch: | lp:~pete-woods/ubuntu-app-launch/port-some-c-to-cpp |
Merge into: | lp:ubuntu-app-launch |
Prerequisite: | lp:~ci-train-bot/ubuntu-app-launch/ubuntu-app-launch-ubuntu-zesty-2675 |
Diff against target: |
946 lines (+374/-315) 6 files modified
libubuntu-app-launch/CMakeLists.txt (+1/-1) libubuntu-app-launch/jobs-base.cpp (+0/-23) libubuntu-app-launch/jobs-base.h (+0/-1) libubuntu-app-launch/jobs-systemd.cpp (+6/-7) libubuntu-app-launch/second-exec-core.cpp (+347/-274) libubuntu-app-launch/second-exec-core.h (+20/-9) |
To merge this branch: | bzr merge lp:~pete-woods/ubuntu-app-launch/port-some-c-to-cpp |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Needs Fixing | |
Indicator Applet Developers | Pending | ||
Review via email: mp+321866@code.launchpad.net |
Commit message
Initial port of second-exec-core.c to C++
* Still has remaining lifecycle issue
Description of the change
Initial port of second-exec-core.c to C++
* Still has remaining lifecycle issue
unity-api-1-bot (unity-api-1-bot) wrote : | # |
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:318
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 310. By Ted Gould
-
Cleanup registry references to make them consistent (LP: #1676361)
Approved by: Charles Kerr
- 311. By Ted Gould
-
Watch system folders for apps added and removed (LP: #1630997, #1672392)
Approved by: Marcus Tomlinson, Pete Woods
- 312. By Ted Gould
-
Wait with a timeout for the libertine service to start
Approved by: Pete Woods
- 313. By CI Train Bot Account
-
Bump version for new AppID methods
- 314. By Ted Gould
-
Provide equality operators for Application and Application:
:Instance objects. (LP: #1677345) Approved by: Pete Woods
- 315. By Ted Gould
-
Force GTK and Qt backends when using XMir
Approved by: Pete Woods
- 316. By CI Train Bot Account
-
Releasing 0.12+17.
04.20170404. 2-0ubuntu1 - 317. By Pete Woods
-
Initial port of second-exec-core.c to C++
* Still has remaining lifecycle issue
Unmerged revisions
- 317. By Pete Woods
-
Initial port of second-exec-core.c to C++
* Still has remaining lifecycle issue
Preview Diff
1 | === modified file 'libubuntu-app-launch/CMakeLists.txt' |
2 | --- libubuntu-app-launch/CMakeLists.txt 2017-03-20 10:13:50 +0000 |
3 | +++ libubuntu-app-launch/CMakeLists.txt 2017-04-05 12:08:51 +0000 |
4 | @@ -80,7 +80,7 @@ |
5 | |
6 | set(LAUNCHER_SOURCES |
7 | ubuntu-app-launch.cpp |
8 | -second-exec-core.c |
9 | +second-exec-core.cpp |
10 | ubuntu-app-launch-trace.c |
11 | utils.c |
12 | utils-shared.c |
13 | |
14 | === modified file 'libubuntu-app-launch/jobs-base.cpp' |
15 | --- libubuntu-app-launch/jobs-base.cpp 2017-04-05 12:08:51 +0000 |
16 | +++ libubuntu-app-launch/jobs-base.cpp 2017-04-05 12:08:51 +0000 |
17 | @@ -1053,29 +1053,6 @@ |
18 | } |
19 | } |
20 | |
21 | -/** Reformat a C++ vector of URLs into a C GStrv of strings |
22 | - |
23 | - \param urls Vector of URLs to make into C strings |
24 | -*/ |
25 | -GCharVUPtr Base::urlsToStrv(const std::vector<Application::URL>& urls) |
26 | -{ |
27 | - if (urls.empty()) |
28 | - { |
29 | - return GCharVUPtr(nullptr, &g_strfreev); |
30 | - } |
31 | - |
32 | - auto array = g_array_new(TRUE, FALSE, sizeof(gchar*)); |
33 | - |
34 | - for (auto url : urls) |
35 | - { |
36 | - auto str = g_strdup(url.value().c_str()); |
37 | - g_debug("Converting URL: %s", str); |
38 | - g_array_append_val(array, str); |
39 | - } |
40 | - |
41 | - return unique_gcharv((gchar**)g_array_free(array, FALSE)); |
42 | -} |
43 | - |
44 | } // namespace instance |
45 | |
46 | } // namespace jobs |
47 | |
48 | === modified file 'libubuntu-app-launch/jobs-base.h' |
49 | --- libubuntu-app-launch/jobs-base.h 2017-04-05 12:08:51 +0000 |
50 | +++ libubuntu-app-launch/jobs-base.h 2017-04-05 12:08:51 +0000 |
51 | @@ -91,7 +91,6 @@ |
52 | static void oomValueToPid(pid_t pid, const oom::Score oomvalue); |
53 | static void oomValueToPidHelper(pid_t pid, const oom::Score oomvalue); |
54 | static std::string pidToOomPath(pid_t pid); |
55 | - static GCharVUPtr urlsToStrv(const std::vector<Application::URL>& urls); |
56 | }; |
57 | |
58 | } // namespace instance |
59 | |
60 | === modified file 'libubuntu-app-launch/jobs-systemd.cpp' |
61 | --- libubuntu-app-launch/jobs-systemd.cpp 2017-04-05 12:08:51 +0000 |
62 | +++ libubuntu-app-launch/jobs-systemd.cpp 2017-04-05 12:08:51 +0000 |
63 | @@ -513,13 +513,12 @@ |
64 | g_debug("Remote error: %s", remote_error); |
65 | if (g_strcmp0(remote_error, "org.freedesktop.systemd1.UnitExists") == 0) |
66 | { |
67 | - auto urls = instance::SystemD::urlsToStrv(data->ptr->urls_); |
68 | - second_exec(data->bus.get(), /* DBus */ |
69 | - data->ptr->registry_->thread.getCancellable().get(), /* cancellable */ |
70 | - data->ptr->primaryPid(), /* primary pid */ |
71 | - std::string(data->ptr->appId_).c_str(), /* appid */ |
72 | - data->ptr->instance_.c_str(), /* instance */ |
73 | - urls.get()); /* urls */ |
74 | + second_exec(data->bus, /* DBus */ |
75 | + data->ptr->registry_->thread.getCancellable(), /* cancellable */ |
76 | + data->ptr->primaryPid(), /* primary pid */ |
77 | + std::string(data->ptr->appId_), /* appid */ |
78 | + data->ptr->instance_, /* instance */ |
79 | + data->ptr->urls_); /* urls */ |
80 | } |
81 | |
82 | g_free(remote_error); |
83 | |
84 | === renamed file 'libubuntu-app-launch/second-exec-core.c' => 'libubuntu-app-launch/second-exec-core.cpp' |
85 | --- libubuntu-app-launch/second-exec-core.c 2017-03-14 22:41:03 +0000 |
86 | +++ libubuntu-app-launch/second-exec-core.cpp 2017-04-05 12:08:51 +0000 |
87 | @@ -1,5 +1,5 @@ |
88 | /* |
89 | - * Copyright 2013 Canonical Ltd. |
90 | + * Copyright 2013-2017 Canonical Ltd. |
91 | * |
92 | * This program is free software: you can redistribute it and/or modify it |
93 | * under the terms of the GNU General Public License version 3, as published |
94 | @@ -15,138 +15,230 @@ |
95 | * |
96 | * Authors: |
97 | * Ted Gould <ted.gould@canonical.com> |
98 | + * Pete Woods <pete.woods@canonical.com> |
99 | */ |
100 | |
101 | #include <gio/gio.h> |
102 | #include "libubuntu-app-launch/ubuntu-app-launch.h" |
103 | -#include "utils.h" |
104 | #include "second-exec-core.h" |
105 | +#include "signal-unsubscriber.h" |
106 | #include "ubuntu-app-launch-trace.h" |
107 | #include "ual-tracepoint.h" |
108 | |
109 | -typedef struct { |
110 | - GDBusConnection * bus; |
111 | - gchar * appid; |
112 | - gchar * instanceid; |
113 | - gchar ** input_uris; |
114 | - GPid app_pid; |
115 | - guint connections_open; |
116 | - GVariant * app_data; |
117 | - gchar * dbus_path; |
118 | - guint64 unity_starttime; |
119 | - GSource * timer; |
120 | - guint signal; |
121 | -} second_exec_t; |
122 | - |
123 | -static void second_exec_complete (second_exec_t * data); |
124 | - |
125 | -static GSource * |
126 | -thread_default_timeout (guint interval, GSourceFunc func, gpointer data) |
127 | -{ |
128 | - GSource * src = g_timeout_source_new(interval); |
129 | - GMainContext * context = g_main_context_get_thread_default(); |
130 | - |
131 | - g_source_set_callback(src, func, data, NULL); |
132 | - |
133 | - g_source_attach(src, context); |
134 | +#include <unity/util/GlibMemory.h> |
135 | + |
136 | +#include <iomanip> |
137 | +#include <sstream> |
138 | +#include <unordered_map> |
139 | + |
140 | +using namespace std; |
141 | +using namespace unity::util; |
142 | + |
143 | +namespace ubuntu |
144 | +{ |
145 | +namespace app_launch |
146 | +{ |
147 | +namespace |
148 | +{ |
149 | + |
150 | +struct GSourceClear |
151 | +{ |
152 | + void operator()(GSource* source) |
153 | + { |
154 | + if (source != nullptr) |
155 | + { |
156 | + g_source_destroy(source); |
157 | + g_source_unref(source); |
158 | + } |
159 | + } |
160 | +}; |
161 | + |
162 | + |
163 | +class second_exec_t: public enable_shared_from_this<second_exec_t> |
164 | +{ |
165 | +public: |
166 | + second_exec_t(shared_ptr<GDBusConnection> bus, const string& appid, const string& instanceid, const vector<Application::URL>& input_uris, GPid app_pid); |
167 | + |
168 | + ~second_exec_t(); |
169 | + |
170 | + void |
171 | + init (); |
172 | + |
173 | +private: |
174 | + class get_pid_t |
175 | + { |
176 | + public: |
177 | + get_pid_t(const string& name, shared_ptr<GDBusConnection> bus, shared_ptr<second_exec_t> data); |
178 | + |
179 | + private: |
180 | + static void |
181 | + get_pid_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
182 | + { |
183 | + ((get_pid_t *)user_data)->get_pid(object, res); |
184 | + } |
185 | + |
186 | + void |
187 | + get_pid (GObject * object, GAsyncResult * res); |
188 | + |
189 | + string name; |
190 | + |
191 | + shared_ptr<second_exec_t> data; |
192 | + }; |
193 | + |
194 | + /* Unity didn't respond in time, continue on */ |
195 | + static gboolean |
196 | + timer_cb (gpointer user_data); |
197 | + |
198 | + static void |
199 | + send_open_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
200 | + { |
201 | + ((second_exec_t*) user_data)->send_open(object, res); |
202 | + } |
203 | + |
204 | + void |
205 | + app_id_to_dbus_path (); |
206 | + |
207 | + void |
208 | + send_open (GObject * object, GAsyncResult * res); |
209 | + |
210 | + void |
211 | + contact_app (GDBusConnection * bus, const string& dbus_name); |
212 | + |
213 | + void |
214 | + find_appid_pid (); |
215 | + |
216 | + void |
217 | + connection_count_dec (); |
218 | + |
219 | + static void |
220 | + unity_resume_cb (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
221 | + { |
222 | + ((second_exec_t*) user_data)->unity_resume(connection, sender, path, interface, signal, params); |
223 | + } |
224 | + |
225 | + void |
226 | + unity_resume(GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params); |
227 | + |
228 | + void |
229 | + parse_uris (); |
230 | + |
231 | + static GSourceUPtr |
232 | + thread_default_timeout (guint interval, GSourceFunc func, gpointer data); |
233 | + |
234 | + void finish(); |
235 | + |
236 | + static unordered_map<second_exec_t*, shared_ptr<second_exec_t>> SECOND_EXEC_INSTANCES_; |
237 | + |
238 | + shared_ptr<GDBusConnection> bus_; |
239 | + string appid_; |
240 | + string instanceid_; |
241 | + vector<Application::URL> input_uris_; |
242 | + GPid app_pid_; |
243 | + guint connections_open {0}; |
244 | + GVariantSPtr app_data{nullptr, GVariantDeleter()}; |
245 | + string dbus_path; |
246 | + guint64 unity_starttime {0}; |
247 | + GSourceSPtr timer{nullptr, GSourceClear()}; |
248 | + ManagedDBusSignalConnection signal {DBusSignalUnsubscriber()}; |
249 | +}; |
250 | + |
251 | +unordered_map<second_exec_t*, shared_ptr<second_exec_t>> second_exec_t::SECOND_EXEC_INSTANCES_; |
252 | + |
253 | +GSourceUPtr |
254 | +second_exec_t::thread_default_timeout (guint interval, GSourceFunc func, gpointer data) |
255 | +{ |
256 | + auto src = unique_glib(g_timeout_source_new(interval)); |
257 | + auto context = unique_glib(g_main_context_get_thread_default()); |
258 | + |
259 | + g_source_set_callback(src.get(), func, data, nullptr); |
260 | + |
261 | + g_source_attach(src.get(), context.get()); |
262 | |
263 | return src; |
264 | } |
265 | |
266 | /* Unity didn't respond in time, continue on */ |
267 | -static gboolean |
268 | -timer_cb (gpointer user_data) |
269 | +gboolean |
270 | +second_exec_t::timer_cb (gpointer user_data) |
271 | { |
272 | - ual_tracepoint(second_exec_resume_timeout, ((second_exec_t *)user_data)->appid); |
273 | + auto data = (second_exec_t *)user_data; |
274 | + ual_tracepoint(second_exec_resume_timeout, data->appid_.c_str()); |
275 | g_warning("Unity didn't respond in 500ms to resume the app"); |
276 | |
277 | - second_exec_complete(user_data); |
278 | + data->finish(); |
279 | return G_SOURCE_REMOVE; |
280 | } |
281 | |
282 | /* Lower the connection count and process if it gets to zero */ |
283 | -static void |
284 | -connection_count_dec (second_exec_t * data) |
285 | +void |
286 | +second_exec_t::connection_count_dec () |
287 | { |
288 | - ual_tracepoint(second_exec_connection_complete, data->appid); |
289 | - data->connections_open--; |
290 | - if (data->connections_open == 0) { |
291 | + ual_tracepoint(second_exec_connection_complete, appid_.c_str()); |
292 | + connections_open--; |
293 | + if (connections_open == 0) { |
294 | g_debug("Finished finding connections"); |
295 | /* Check time here, either we've already heard from |
296 | Unity and we should send the data to the app (quit) or |
297 | we should wait some more */ |
298 | - guint64 timespent = g_get_monotonic_time() - data->unity_starttime; |
299 | + guint64 timespent = g_get_monotonic_time() - unity_starttime; |
300 | if (timespent > 500 /* ms */ * 1000 /* ms to us */) { |
301 | - second_exec_complete(data); |
302 | + finish(); |
303 | + return; |
304 | } else { |
305 | g_debug("Timer Set"); |
306 | - data->timer = thread_default_timeout(500 - (timespent / 1000), timer_cb, data); |
307 | + timer = thread_default_timeout(500 - (timespent / 1000), timer_cb, this); |
308 | } |
309 | } |
310 | - return; |
311 | } |
312 | |
313 | /* Called when Unity is done unfreezing the application, if we're |
314 | done determining the PID, we can send signals */ |
315 | -static void |
316 | -unity_resume_cb (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
317 | +void |
318 | +second_exec_t::unity_resume(GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params) |
319 | { |
320 | - second_exec_t * data = (second_exec_t *)user_data; |
321 | g_debug("Unity Completed Resume"); |
322 | - ual_tracepoint(second_exec_resume_complete, data->appid); |
323 | - |
324 | - if (data->timer != NULL) { |
325 | - g_source_destroy(data->timer); |
326 | - g_source_unref(data->timer); |
327 | - data->timer = NULL; |
328 | - } |
329 | - |
330 | - if (data->connections_open == 0) { |
331 | - second_exec_complete(data); |
332 | + ual_tracepoint(second_exec_resume_complete, appid_.c_str()); |
333 | + |
334 | + timer.reset(); |
335 | + |
336 | + if (connections_open == 0) { |
337 | + finish(); |
338 | } else { |
339 | /* Make it look like we started *forever* ago */ |
340 | - data->unity_starttime = 0; |
341 | + unity_starttime = 0; |
342 | } |
343 | - |
344 | - return; |
345 | } |
346 | |
347 | /* Turn the input string into something we can send to apps */ |
348 | -static void |
349 | -parse_uris (second_exec_t * data) |
350 | +void |
351 | +second_exec_t::parse_uris () |
352 | { |
353 | - if (data->app_data != NULL) { |
354 | + if (app_data) { |
355 | /* Already done */ |
356 | return; |
357 | } |
358 | |
359 | - GVariant * uris = NULL; |
360 | + GVariant * uris = nullptr; |
361 | |
362 | - if (data->input_uris == NULL) { |
363 | - uris = g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0); |
364 | + if (input_uris_.empty()) { |
365 | + uris = g_variant_new_array(G_VARIANT_TYPE_STRING, nullptr, 0); |
366 | } else { |
367 | GVariantBuilder builder; |
368 | g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); |
369 | |
370 | - int i; |
371 | - for (i = 0; data->input_uris[i] != NULL; i++) { |
372 | - g_variant_builder_add_value(&builder, g_variant_new_string(data->input_uris[i])); |
373 | + for (const auto& uri: input_uris_) { |
374 | + g_variant_builder_add_value(&builder, g_variant_new_string(uri.value().c_str())); |
375 | } |
376 | |
377 | uris = g_variant_builder_end(&builder); |
378 | } |
379 | |
380 | - GVariant * platform = g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0); |
381 | - |
382 | GVariantBuilder tuple; |
383 | g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); |
384 | g_variant_builder_add_value(&tuple, uris); |
385 | - g_variant_builder_add_value(&tuple, platform); |
386 | - |
387 | - data->app_data = g_variant_builder_end(&tuple); |
388 | - g_variant_ref_sink(data->app_data); |
389 | - |
390 | - return; |
391 | + g_variant_builder_add_value(&tuple, g_variant_new_array(G_VARIANT_TYPE("{sv}"), nullptr, 0)); |
392 | + |
393 | + app_data = unique_glib(g_variant_ref_sink(g_variant_builder_end(&tuple))); |
394 | } |
395 | |
396 | /* Finds us our dbus path to use. Basically this is the name |
397 | @@ -155,322 +247,303 @@ |
398 | |
399 | http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#dbus |
400 | */ |
401 | -static void |
402 | -app_id_to_dbus_path (second_exec_t * data) |
403 | +void |
404 | +second_exec_t::app_id_to_dbus_path () |
405 | { |
406 | - if (data->dbus_path != NULL) { |
407 | + if (!dbus_path.empty()) { |
408 | return; |
409 | } |
410 | |
411 | - GString * str = g_string_sized_new(strlen(data->appid) + 2); /* base case, we just need a / and a null */ |
412 | - g_string_append_c(str, '/'); |
413 | - |
414 | - int i; |
415 | - for (i = 0; data->appid[i] != '\0'; i++) { |
416 | - if ((data->appid[i] >= 'a' && data->appid[i] <= 'z') || |
417 | - (data->appid[i] >= 'A' && data->appid[i] <= 'Z') || |
418 | - (data->appid[i] >= '0' && data->appid[i] <= '9' && i != 0)) { |
419 | - g_string_append_c(str, data->appid[i]); |
420 | - continue; |
421 | - } |
422 | - |
423 | - g_string_append_printf(str, "_%2x", data->appid[i]); |
424 | + stringstream str; |
425 | + auto defaultFlags = str.flags(); |
426 | + str << "/"; |
427 | + |
428 | + bool first = true; |
429 | + for (const auto c: appid_) { |
430 | + if ((c >= 'a' && c <= 'z') || |
431 | + (c >= 'A' && c <= 'Z') || |
432 | + (c >= '0' && c <= '9' && !first)) |
433 | + { |
434 | + str << c; |
435 | + } |
436 | + else |
437 | + { |
438 | + str << "_" << setfill('0') << setw(2) << hex << c; |
439 | + str.flags(defaultFlags); |
440 | + } |
441 | + first = false; |
442 | } |
443 | |
444 | - data->dbus_path = g_string_free(str, FALSE); |
445 | - g_debug("DBus Path: %s", data->dbus_path); |
446 | - |
447 | - return; |
448 | + dbus_path = str.str(); |
449 | + g_debug("DBus Path: %s", dbus_path.c_str()); |
450 | } |
451 | |
452 | /* Finish the send and decrement the counter */ |
453 | -static void |
454 | -send_open_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
455 | +void |
456 | +second_exec_t::send_open (GObject * object, GAsyncResult * res) |
457 | { |
458 | - GError * error = NULL; |
459 | + GError * error = nullptr; |
460 | |
461 | - ual_tracepoint(second_exec_app_contacted, ((second_exec_t *)user_data)->appid); |
462 | + ual_tracepoint(second_exec_app_contacted, appid_.c_str()); |
463 | |
464 | g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); |
465 | |
466 | - if (error != NULL) { |
467 | - ual_tracepoint(second_exec_app_error, ((second_exec_t *)user_data)->appid); |
468 | + if (error != nullptr) { |
469 | + ual_tracepoint(second_exec_app_error, appid_.c_str()); |
470 | /* Mostly just to free the error, but printing for debugging */ |
471 | g_debug("Unable to send Open: %s", error->message); |
472 | - g_error_free(error); |
473 | + g_clear_error(&error); |
474 | } |
475 | |
476 | - connection_count_dec(user_data); |
477 | - return; |
478 | + connection_count_dec(); |
479 | } |
480 | |
481 | /* Sends the Open message to the connection with the URIs we were given */ |
482 | -static void |
483 | -contact_app (GDBusConnection * bus, const gchar * dbus_name, second_exec_t * data) |
484 | +void |
485 | +second_exec_t::contact_app (GDBusConnection * bus, const string& dbus_name) |
486 | { |
487 | - ual_tracepoint(second_exec_contact_app, data->appid, dbus_name); |
488 | + ual_tracepoint(second_exec_contact_app, appid_.c_str(), dbus_name.c_str()); |
489 | |
490 | - parse_uris(data); |
491 | - app_id_to_dbus_path(data); |
492 | + parse_uris(); |
493 | + app_id_to_dbus_path(); |
494 | |
495 | /* Using the FD.o Application interface */ |
496 | g_dbus_connection_call(bus, |
497 | - dbus_name, |
498 | - data->dbus_path, |
499 | + dbus_name.c_str(), |
500 | + dbus_path.c_str(), |
501 | "org.freedesktop.Application", |
502 | "Open", |
503 | - data->app_data, |
504 | - NULL, |
505 | - G_DBUS_CALL_FLAGS_NONE, |
506 | - -1, |
507 | - NULL, |
508 | - send_open_cb, data); |
509 | - |
510 | - g_debug("Sending Open request to: %s", dbus_name); |
511 | - |
512 | - return; |
513 | -} |
514 | - |
515 | -typedef struct { |
516 | - gchar * name; |
517 | - second_exec_t * data; |
518 | -} get_pid_t; |
519 | + app_data.get(), |
520 | + NULL, |
521 | + G_DBUS_CALL_FLAGS_NONE, |
522 | + -1, |
523 | + NULL, |
524 | + second_exec_t::send_open_cb, this); |
525 | + |
526 | + g_debug("Sending Open request to: %s", dbus_name.c_str()); |
527 | +} |
528 | + |
529 | +second_exec_t::get_pid_t::get_pid_t(const string& _name, shared_ptr<GDBusConnection> bus, shared_ptr<second_exec_t> _data) : |
530 | + name(_name), data(_data) |
531 | +{ |
532 | + /* Get the PIDs */ |
533 | + g_dbus_connection_call(bus.get(), |
534 | + "org.freedesktop.DBus", |
535 | + "/", |
536 | + "org.freedesktop.DBus", |
537 | + "GetConnectionUnixProcessID", |
538 | + g_variant_new("(s)", name.c_str()), |
539 | + G_VARIANT_TYPE("(u)"), |
540 | + G_DBUS_CALL_FLAGS_NONE, |
541 | + -1, |
542 | + nullptr, |
543 | + get_pid_t::get_pid_cb, this); |
544 | +} |
545 | |
546 | /* Gets the PID for a connection, and if it matches the one we're looking |
547 | for then it tries to send a message to that connection */ |
548 | -static void |
549 | -get_pid_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
550 | +void |
551 | +second_exec_t::get_pid_t::get_pid (GObject * object, GAsyncResult * res) |
552 | { |
553 | - get_pid_t * data = (get_pid_t *)user_data; |
554 | - GError * error = NULL; |
555 | - GVariant * vpid = NULL; |
556 | - |
557 | - ual_tracepoint(second_exec_got_pid, data->data->appid, data->name); |
558 | - |
559 | - vpid = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); |
560 | - |
561 | - if (error != NULL) { |
562 | - g_warning("Unable to query PID for dbus name '%s': %s", data->name, error->message); |
563 | - g_error_free(error); |
564 | + GError * error = nullptr; |
565 | + |
566 | + ual_tracepoint(second_exec_got_pid, data->appid_.c_str(), name.c_str()); |
567 | + |
568 | + auto vpid = unique_glib(g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error)); |
569 | + |
570 | + if (error != nullptr) { |
571 | + g_warning("Unable to query PID for dbus name '%s': %s", name.c_str(), error->message); |
572 | + g_clear_error(&error); |
573 | |
574 | /* Lowering the connection count, this one is terminal, even if in error */ |
575 | - connection_count_dec(data->data); |
576 | - |
577 | - g_free(data->name); |
578 | - g_free(data); |
579 | - |
580 | - return; |
581 | - } |
582 | - |
583 | - guint pid = 0; |
584 | - g_variant_get(vpid, "(u)", &pid); |
585 | - g_variant_unref(vpid); |
586 | - |
587 | - if (pid == data->data->app_pid) { |
588 | - /* Trying to send a message to the connection */ |
589 | - contact_app(G_DBUS_CONNECTION(object), data->name, data->data); |
590 | + data->connection_count_dec(); |
591 | } else { |
592 | - /* See if we can quit now */ |
593 | - connection_count_dec(data->data); |
594 | + GPid pid = 0; |
595 | + g_variant_get(vpid.get(), "(u)", &pid); |
596 | + |
597 | + if (pid == data->app_pid_) { |
598 | + /* Trying to send a message to the connection */ |
599 | + data->contact_app(G_DBUS_CONNECTION(object), name); |
600 | + } else { |
601 | + /* See if we can quit now */ |
602 | + data->connection_count_dec(); |
603 | + } |
604 | } |
605 | |
606 | - g_free(data->name); |
607 | - g_free(data); |
608 | - |
609 | - return; |
610 | + delete this; |
611 | } |
612 | |
613 | /* Starts to look for the PID and the connections for that PID */ |
614 | -static void |
615 | -find_appid_pid (GDBusConnection * session, second_exec_t * data) |
616 | +void |
617 | +second_exec_t::find_appid_pid () |
618 | { |
619 | - GError * error = NULL; |
620 | + GError * error = nullptr; |
621 | |
622 | /* List all the connections on dbus. This sucks that we have to do |
623 | this, but in the future we should add DBus API to do this lookup |
624 | instead of having to do it with a bunch of requests */ |
625 | - GVariant * listnames = g_dbus_connection_call_sync(session, |
626 | + auto listnames = unique_glib(g_dbus_connection_call_sync(bus_.get(), |
627 | "org.freedesktop.DBus", |
628 | "/", |
629 | "org.freedesktop.DBus", |
630 | "ListNames", |
631 | - NULL, |
632 | + nullptr, |
633 | G_VARIANT_TYPE("(as)"), |
634 | G_DBUS_CALL_FLAGS_NONE, |
635 | -1, |
636 | - NULL, |
637 | - &error); |
638 | + nullptr, |
639 | + &error)); |
640 | |
641 | - if (error != NULL) { |
642 | + if (error != nullptr) { |
643 | g_warning("Unable to get list of names from DBus: %s", error->message); |
644 | - g_error_free(error); |
645 | + g_clear_error(&error); |
646 | return; |
647 | } |
648 | |
649 | g_debug("Got bus names"); |
650 | - ual_tracepoint(second_exec_got_dbus_names, data->appid); |
651 | + ual_tracepoint(second_exec_got_dbus_names, appid_.c_str()); |
652 | |
653 | - g_debug("Primary PID: %d", data->app_pid); |
654 | - ual_tracepoint(second_exec_got_primary_pid, data->appid); |
655 | + g_debug("Primary PID: %d", app_pid_); |
656 | + ual_tracepoint(second_exec_got_primary_pid, appid_.c_str()); |
657 | |
658 | /* Get the names */ |
659 | - GVariant * names = g_variant_get_child_value(listnames, 0); |
660 | + auto names = unique_glib(g_variant_get_child_value(listnames.get(), 0)); |
661 | GVariantIter iter; |
662 | - g_variant_iter_init(&iter, names); |
663 | - gchar * name = NULL; |
664 | + g_variant_iter_init(&iter, names.get()); |
665 | + gchar * name = nullptr; |
666 | |
667 | while (g_variant_iter_loop(&iter, "s", &name)) { |
668 | /* We only want to ask each connection once, this makes that so */ |
669 | if (!g_dbus_is_unique_name(name)) { |
670 | continue; |
671 | } |
672 | - |
673 | - get_pid_t * pid_data = g_new0(get_pid_t, 1); |
674 | - pid_data->data = data; |
675 | - pid_data->name = g_strdup(name); |
676 | - |
677 | - ual_tracepoint(second_exec_request_pid, data->appid, pid_data->name); |
678 | - |
679 | - /* Get the PIDs */ |
680 | - g_dbus_connection_call(session, |
681 | - "org.freedesktop.DBus", |
682 | - "/", |
683 | - "org.freedesktop.DBus", |
684 | - "GetConnectionUnixProcessID", |
685 | - g_variant_new("(s)", name), |
686 | - G_VARIANT_TYPE("(u)"), |
687 | - G_DBUS_CALL_FLAGS_NONE, |
688 | - -1, |
689 | - NULL, |
690 | - get_pid_cb, pid_data); |
691 | - |
692 | - data->connections_open++; |
693 | + |
694 | + ual_tracepoint(second_exec_request_pid, appid_.c_str(), name); |
695 | + |
696 | + // FIXME This object deletes itself |
697 | + new get_pid_t(string(name), bus_, shared_from_this()); |
698 | + |
699 | + connections_open++; |
700 | } |
701 | - |
702 | - g_variant_unref(names); |
703 | - g_variant_unref(listnames); |
704 | - |
705 | - return; |
706 | -} |
707 | - |
708 | -gboolean |
709 | -second_exec (GDBusConnection * session, GCancellable * cancel, GPid pid, const gchar * app_id, const gchar * instance_id, gchar ** appuris) |
710 | -{ |
711 | - ual_tracepoint(second_exec_start, app_id); |
712 | - GError * error = NULL; |
713 | - |
714 | - /* Setup our continuation data */ |
715 | - second_exec_t * data = g_new0(second_exec_t, 1); |
716 | - data->appid = g_strdup(app_id); |
717 | - data->instanceid = g_strdup(instance_id); |
718 | - data->input_uris = g_strdupv(appuris); |
719 | - data->bus = g_object_ref(session); |
720 | - data->app_pid = pid; |
721 | +} |
722 | + |
723 | +second_exec_t::second_exec_t(shared_ptr<GDBusConnection> bus, const string& appid, const string& instanceid, const vector<Application::URL>& input_uris, GPid app_pid) : |
724 | + bus_(bus), appid_(appid), instanceid_(instanceid), input_uris_(input_uris), app_pid_(app_pid) |
725 | +{ |
726 | + // can't use for init, due to shared_from_this restriction |
727 | +} |
728 | + |
729 | +void |
730 | +second_exec_t::init() |
731 | +{ |
732 | + ual_tracepoint(second_exec_start, appid_.c_str()); |
733 | |
734 | /* Set up listening for the unfrozen signal from Unity */ |
735 | - data->signal = g_dbus_connection_signal_subscribe(session, |
736 | - NULL, /* sender */ |
737 | + signal = managedDBusSignalConnection(g_dbus_connection_signal_subscribe(bus_.get(), |
738 | + nullptr, /* sender */ |
739 | "com.canonical.UbuntuAppLaunch", /* interface */ |
740 | "UnityResumeResponse", /* signal */ |
741 | "/", /* path */ |
742 | - app_id, /* arg0 */ |
743 | + appid_.c_str(), /* arg0 */ |
744 | G_DBUS_SIGNAL_FLAGS_NONE, |
745 | - unity_resume_cb, data, |
746 | - NULL); /* user data destroy */ |
747 | + second_exec_t::unity_resume_cb, this, |
748 | + nullptr), /* user data destroy */ |
749 | + bus_); |
750 | |
751 | g_debug("Sending resume request"); |
752 | - ual_tracepoint(second_exec_emit_resume, app_id); |
753 | + ual_tracepoint(second_exec_emit_resume, appid_.c_str()); |
754 | + |
755 | + GError * error = nullptr; |
756 | |
757 | /* Send unfreeze to to Unity */ |
758 | - g_dbus_connection_emit_signal(session, |
759 | - NULL, /* destination */ |
760 | + g_dbus_connection_emit_signal(bus_.get(), |
761 | + nullptr, /* destination */ |
762 | "/", /* path */ |
763 | "com.canonical.UbuntuAppLaunch", /* interface */ |
764 | "UnityResumeRequest", /* signal */ |
765 | - g_variant_new("(ss)", app_id, instance_id), |
766 | + g_variant_new("(ss)", appid_.c_str(), instanceid_.c_str()), |
767 | &error); |
768 | |
769 | /* Now we start a race, we try to get to the point of knowing who |
770 | to send things to, and Unity is unfrezing it. When both are |
771 | done we can send something to the app */ |
772 | - data->unity_starttime = g_get_monotonic_time(); |
773 | + unity_starttime = g_get_monotonic_time(); |
774 | |
775 | - if (error != NULL) { |
776 | + if (error != nullptr) { |
777 | /* On error let's not wait for Unity */ |
778 | g_warning("Unable to signal Unity: %s", error->message); |
779 | - g_error_free(error); |
780 | - error = NULL; |
781 | - data->unity_starttime = 0; |
782 | + g_clear_error(&error); |
783 | + unity_starttime = 0; |
784 | } |
785 | |
786 | /* If we've got something to give out, start looking for how */ |
787 | - if (data->input_uris != NULL) { |
788 | - find_appid_pid(session, data); |
789 | + if (!input_uris_.empty()) { |
790 | + find_appid_pid(); |
791 | } else { |
792 | g_debug("No URIs to send"); |
793 | } |
794 | |
795 | /* Loop and wait for everything to align */ |
796 | - if (data->connections_open == 0) { |
797 | - if (data->unity_starttime == 0) { |
798 | - second_exec_complete(data); |
799 | - } else { |
800 | - data->timer = thread_default_timeout(500, timer_cb, data); |
801 | + if (connections_open == 0) { |
802 | + if (unity_starttime != 0) { |
803 | + timer = thread_default_timeout(500, timer_cb, this); |
804 | + SECOND_EXEC_INSTANCES_.insert(make_pair(this, shared_from_this())); |
805 | } |
806 | } |
807 | - |
808 | - return TRUE; |
809 | -} |
810 | - |
811 | -static void |
812 | -second_exec_complete (second_exec_t * data) |
813 | -{ |
814 | - GError * error = NULL; |
815 | - ual_tracepoint(second_exec_emit_focus, data->appid); |
816 | +} |
817 | + |
818 | +void second_exec_t::finish() |
819 | +{ |
820 | + SECOND_EXEC_INSTANCES_.erase(this); |
821 | +} |
822 | + |
823 | +second_exec_t::~second_exec_t() |
824 | +{ |
825 | + GError * error = nullptr; |
826 | + ual_tracepoint(second_exec_emit_focus, appid_.c_str()); |
827 | |
828 | /* Now that we're done sending the info to the app, we can ask |
829 | Unity to focus the application. */ |
830 | - g_dbus_connection_emit_signal(data->bus, |
831 | - NULL, /* destination */ |
832 | + g_dbus_connection_emit_signal(bus_.get(), |
833 | + nullptr, /* destination */ |
834 | "/", /* path */ |
835 | "com.canonical.UbuntuAppLaunch", /* interface */ |
836 | "UnityFocusRequest", /* signal */ |
837 | - g_variant_new("(ss)", data->appid, data->instanceid), |
838 | + g_variant_new("(ss)", appid_.c_str(), instanceid_.c_str()), |
839 | &error); |
840 | |
841 | - if (error != NULL) { |
842 | + if (error != nullptr) |
843 | + { |
844 | g_warning("Unable to request focus to Unity: %s", error->message); |
845 | - g_error_free(error); |
846 | - error = NULL; |
847 | + g_clear_error(&error); |
848 | } |
849 | |
850 | /* Make sure the signal hits the bus */ |
851 | - g_dbus_connection_flush_sync(data->bus, NULL, &error); |
852 | + g_dbus_connection_flush_sync(bus_.get(), nullptr, &error); |
853 | if (error != NULL) { |
854 | g_warning("Unable to flush session bus: %s", error->message); |
855 | - g_error_free(error); |
856 | - error = NULL; |
857 | + g_clear_error(&error); |
858 | } |
859 | |
860 | - ual_tracepoint(second_exec_finish, data->appid); |
861 | + ual_tracepoint(second_exec_finish, appid_.c_str()); |
862 | g_debug("Second Exec complete"); |
863 | - |
864 | - /* Clean up */ |
865 | - if (data->signal != 0) |
866 | - g_dbus_connection_signal_unsubscribe(data->bus, data->signal); |
867 | - |
868 | - if (data->timer != NULL) { |
869 | - g_source_destroy(data->timer); |
870 | - g_source_unref(data->timer); |
871 | - } |
872 | - g_object_unref(data->bus); |
873 | - if (data->app_data != NULL) |
874 | - g_variant_unref(data->app_data); |
875 | - g_free(data->appid); |
876 | - g_free(data->instanceid); |
877 | - g_strfreev(data->input_uris); |
878 | - g_free(data->dbus_path); |
879 | - g_free(data); |
880 | - |
881 | - return; |
882 | +} |
883 | + |
884 | +} |
885 | + |
886 | +void |
887 | +second_exec (shared_ptr<GDBusConnection> session, shared_ptr<GCancellable> cancel, GPid pid, const string& app_id, const string& instance_id, const vector<Application::URL>& appuris) |
888 | +{ |
889 | + auto t = make_shared<second_exec_t>( |
890 | + session, |
891 | + app_id, |
892 | + instance_id, |
893 | + appuris, |
894 | + pid |
895 | + ); |
896 | + |
897 | + t->init(); |
898 | +} |
899 | + |
900 | +} |
901 | } |
902 | |
903 | === modified file 'libubuntu-app-launch/second-exec-core.h' |
904 | --- libubuntu-app-launch/second-exec-core.h 2016-12-14 23:03:15 +0000 |
905 | +++ libubuntu-app-launch/second-exec-core.h 2017-04-05 12:08:51 +0000 |
906 | @@ -1,6 +1,5 @@ |
907 | - |
908 | /* |
909 | - * Copyright 2013 Canonical Ltd. |
910 | + * Copyright 2013-2017 Canonical Ltd. |
911 | * |
912 | * This program is free software: you can redistribute it and/or modify it |
913 | * under the terms of the GNU General Public License version 3, as published |
914 | @@ -16,13 +15,25 @@ |
915 | * |
916 | * Authors: |
917 | * Ted Gould <ted.gould@canonical.com> |
918 | + * Pete Woods <pete.woods@canonical.com> |
919 | */ |
920 | |
921 | + |
922 | +#pragma once |
923 | + |
924 | #include <gio/gio.h> |
925 | - |
926 | -G_BEGIN_DECLS |
927 | - |
928 | -gboolean second_exec (GDBusConnection * con, GCancellable * cancel, GPid pid, const gchar * app_id, const gchar * instance_id, gchar ** appuris); |
929 | - |
930 | -G_END_DECLS |
931 | - |
932 | +#include <memory> |
933 | +#include <string> |
934 | +#include <vector> |
935 | + |
936 | +#include "application.h" |
937 | + |
938 | +namespace ubuntu |
939 | +{ |
940 | +namespace app_launch |
941 | +{ |
942 | + |
943 | +void second_exec (std::shared_ptr<GDBusConnection> con, std::shared_ptr<GCancellable> cancel, GPid pid, const std::string& app_id, const std::string& instance_id, const std::vector<Application::URL>& appuris); |
944 | + |
945 | +} |
946 | +} |
FAILED: Continuous integration, rev:317 /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/301/ /jenkins. canonical. com/unity- api-1/job/ build/1912/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/1919 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 1701/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= zesty/1701/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 1701/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= zesty/1701 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= zesty/1701/ artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 1701/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= zesty/1701/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/301/ rebuild
https:/