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:
|
|||
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 <[email protected]> |
| 98 | + * Pete Woods <[email protected]> |
| 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 <[email protected]> |
| 918 | + * Pete Woods <[email protected]> |
| 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:/