59
application_start_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
61
app_start_t * data = (app_start_t *)user_data;
62
GError * error = NULL;
63
GVariant * result = NULL;
65
tracepoint(upstart_app_launch, libual_start_message_callback, data->appid);
66
g_debug("Started Message Callback: %s", data->appid);
68
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error);
71
g_variant_unref(result);
74
if (g_dbus_error_is_remote_error(error)) {
75
gchar * remote_error = g_dbus_error_get_remote_error(error);
76
g_debug("Remote error: %s", remote_error);
77
if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0) {
78
second_exec(data->appid, data->uris);
81
g_warning("Unable to emit event to start application: %s", error->message);
91
/* Get the path of the job from Upstart, if we've got it already, we'll just
92
use the cache of the value */
94
get_jobpath (GDBusConnection * con, const gchar * jobname)
96
gchar * cachepath = g_strdup_printf("upstart-app-lauch-job-path-cache-%s", jobname);
97
gpointer cachedata = g_object_get_data(G_OBJECT(con), cachepath);
99
if (cachedata != NULL) {
104
GError * error = NULL;
105
GVariant * job_path_variant = g_dbus_connection_call_sync(con,
106
DBUS_SERVICE_UPSTART,
108
DBUS_INTERFACE_UPSTART,
110
g_variant_new("(s)", jobname),
111
G_VARIANT_TYPE("(o)"),
112
G_DBUS_CALL_FLAGS_NONE,
113
-1, /* timeout: default */
114
NULL, /* cancelable */
118
g_warning("Unable to find job '%s': %s", jobname, error->message);
124
gchar * job_path = NULL;
125
g_variant_get(job_path_variant, "(o)", &job_path);
126
g_variant_unref(job_path_variant);
128
g_object_set_data_full(G_OBJECT(con), cachepath, job_path, g_free);
134
/* Check to see if a legacy app wants us to manage whether they're
135
single instance or not */
137
legacy_single_instance (const gchar * appid)
139
tracepoint(upstart_app_launch, desktop_single_start, appid);
141
GKeyFile * keyfile = keyfile_for_appid(appid, NULL);
143
if (keyfile == NULL) {
144
g_error("Unable to find keyfile for application '%s'", appid);
148
tracepoint(upstart_app_launch, desktop_single_found, appid);
150
gboolean singleinstance = FALSE;
152
if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) {
153
GError * error = NULL;
155
singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error);
158
g_warning("Unable to get single instance key for app '%s': %s", appid, error->message);
160
/* Ensure that if we got an error, we assume standard case */
161
singleinstance = FALSE;
165
g_key_file_free(keyfile);
167
tracepoint(upstart_app_launch, desktop_single_finished, appid, singleinstance ? "single" : "unmanaged");
169
return singleinstance;
91
173
upstart_app_launch_start_application (const gchar * appid, const gchar * const * uris)
93
NihDBusProxy * proxy = NULL;
95
proxy = nih_proxy_create();
175
g_return_val_if_fail(appid != NULL, FALSE);
177
tracepoint(upstart_app_launch, libual_start, appid);
179
GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
180
g_return_val_if_fail(con != NULL, FALSE);
182
/* Determine whether it's a click package by looking for the symlink
183
that is created by the desktop hook */
184
gchar * appiddesktop = g_strdup_printf("%s.desktop", appid);
185
gchar * click_link = NULL;
186
const gchar * link_farm_dir = g_getenv("UPSTART_APP_LAUNCH_LINK_FARM");
187
if (G_LIKELY(link_farm_dir == NULL)) {
188
click_link = g_build_filename(g_get_home_dir(), ".cache", "upstart-app-launch", "desktop", appiddesktop, NULL);
190
click_link = g_build_filename(link_farm_dir, appiddesktop, NULL);
192
g_free(appiddesktop);
193
gboolean click = g_file_test(click_link, G_FILE_TEST_EXISTS);
196
tracepoint(upstart_app_launch, libual_determine_type, appid, click ? "click" : "legacy");
198
/* Figure out the DBus path for the job */
199
const gchar * jobpath = NULL;
201
jobpath = get_jobpath(con, "application-click");
203
jobpath = get_jobpath(con, "application-legacy");
100
gchar * env_appid = g_strdup_printf("APP_ID=%s", appid);
101
gchar * env_uris = NULL;
209
tracepoint(upstart_app_launch, libual_job_path_determined, appid, jobpath);
212
app_start_t * app_start_data = g_new0(app_start_t, 1);
213
app_start_data->appid = g_strdup(appid);
215
/* Build up our environment */
216
GVariantBuilder builder;
217
g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
219
g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
221
g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid)));
103
223
if (uris != NULL) {
104
224
gchar * urisjoin = app_uris_string(uris);
105
env_uris = g_strdup_printf("APP_URIS=%s", urisjoin);
114
gboolean retval = TRUE;
115
if (upstart_emit_event_sync(NULL, proxy, "application-start", env, 0) != 0) {
116
g_warning("Unable to emit signal 'application-start'");
122
nih_unref(proxy, NULL);
225
gchar * urienv = g_strdup_printf("APP_URIS=%s", urisjoin);
226
app_start_data->uris = urisjoin;
227
g_variant_builder_add_value(&builder, g_variant_new_take_string(urienv));
231
if (legacy_single_instance(appid)) {
232
g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID="));
234
gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time());
235
g_variant_builder_add_value(&builder, g_variant_new_take_string(instanceid));
239
g_variant_builder_close(&builder);
240
g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));
242
/* Call the job start function */
243
g_dbus_connection_call(con,
244
DBUS_SERVICE_UPSTART,
246
DBUS_INTERFACE_UPSTART_JOB,
248
g_variant_builder_end(&builder),
250
G_DBUS_CALL_FLAGS_NONE,
252
NULL, /* cancelable */
253
application_start_cb,
256
tracepoint(upstart_app_launch, libual_start_message_sent, appid);
128
stop_job (NihDBusProxy * upstart, const gchar * jobname, const gchar * appname, const gchar * instanceid)
264
stop_job (GDBusConnection * con, const gchar * jobname, const gchar * appname, const gchar * instanceid)
130
266
g_debug("Stopping job %s app_id %s instance_id %s", jobname, appname, instanceid);
131
nih_local char * job_path = NULL;
132
if (upstart_get_job_by_name_sync(NULL, upstart, jobname, &job_path) != 0) {
133
g_warning("Unable to find job '%s'", jobname);
137
NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection,
142
if (job_proxy == NULL) {
143
g_warning("Unable to build proxy to Job '%s'", jobname);
147
gchar * app = g_strdup_printf("APP_ID=%s", appname);
268
const gchar * job_path = get_jobpath(con, jobname);
269
if (job_path == NULL)
272
GVariantBuilder builder;
273
g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
274
g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
276
g_variant_builder_add_value(&builder,
277
g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appname)));
150
279
if (instanceid != NULL) {
151
inst = g_strdup_printf("INSTANCE_ID=%s", instanceid);
160
if (job_class_stop_sync(NULL, job_proxy, env, 0) != 0) {
161
g_warning("Unable to stop job %s app %s instance %s", jobname, appname, instanceid);
166
nih_unref(job_proxy, NULL);
280
g_variant_builder_add_value(&builder,
281
g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instanceid)));
284
g_variant_builder_close(&builder);
285
g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */
287
GError * error = NULL;
288
GVariant * stop_variant = g_dbus_connection_call_sync(con,
289
DBUS_SERVICE_UPSTART,
291
DBUS_INTERFACE_UPSTART_JOB,
293
g_variant_builder_end(&builder),
295
G_DBUS_CALL_FLAGS_NONE,
296
-1, /* timeout: default */
297
NULL, /* cancelable */
301
g_warning("Unable to stop job %s app_id %s instance_id %s: %s", jobname, appname, instanceid, error->message);
305
g_variant_unref(stop_variant);
454
621
return add_session_generic(observer, user_data, "UnityStartingBroadcast", &starting_array, starting_signal_cb);
624
/* Handle the failed signal when it occurs, call the observer */
626
failed_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data)
628
failed_observer_t * observer = (failed_observer_t *)user_data;
629
const gchar * appid = NULL;
630
const gchar * typestr = NULL;
632
tracepoint(upstart_app_launch, observer_start, "failed");
634
if (observer->func != NULL) {
635
upstart_app_launch_app_failed_t type = UPSTART_APP_LAUNCH_APP_FAILED_CRASH;
636
g_variant_get(params, "(&s&s)", &appid, &typestr);
638
if (g_strcmp0("crash", typestr) == 0) {
639
type = UPSTART_APP_LAUNCH_APP_FAILED_CRASH;
640
} else if (g_strcmp0("start-failure", typestr) == 0) {
641
type = UPSTART_APP_LAUNCH_APP_FAILED_START_FAILURE;
643
g_warning("Application failure type '%s' unknown, reporting as a crash", typestr);
646
observer->func(appid, type, observer->user_data);
649
tracepoint(upstart_app_launch, observer_finish, "failed");
458
653
upstart_app_launch_observer_add_app_failed (upstart_app_launch_app_failed_observer_t observer, gpointer user_data)
655
GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
661
failed_observer_t * observert = g_new0(failed_observer_t, 1);
663
observert->conn = conn;
664
observert->func = observer;
665
observert->user_data = user_data;
667
failed_array = g_list_prepend(failed_array, observert);
669
observert->sighandle = g_dbus_connection_signal_subscribe(conn,
671
"com.canonical.UpstartAppLaunch", /* interface */
672
"ApplicationFailed", /* signal */
675
G_DBUS_SIGNAL_FLAGS_NONE,
678
NULL); /* user data destroy */
521
741
upstart_app_launch_observer_delete_app_failed (upstart_app_launch_app_failed_observer_t observer, gpointer user_data)
743
failed_observer_t * observert = NULL;
746
for (look = failed_array; look != NULL; look = g_list_next(look)) {
747
observert = (failed_observer_t *)look->data;
749
if (observert->func == observer && observert->user_data == user_data) {
758
g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle);
759
g_object_unref(observert->conn);
762
failed_array = g_list_delete_link(failed_array, look);
767
typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data);
770
foreach_job_instance (GDBusConnection * con, const gchar * jobname, per_instance_func_t func, gpointer user_data)
772
const gchar * job_path = get_jobpath(con, jobname);
773
if (job_path == NULL)
776
GError * error = NULL;
777
GVariant * instance_tuple = g_dbus_connection_call_sync(con,
778
DBUS_SERVICE_UPSTART,
780
DBUS_INTERFACE_UPSTART_JOB,
783
G_VARIANT_TYPE("(ao)"),
784
G_DBUS_CALL_FLAGS_NONE,
785
-1, /* timeout: default */
786
NULL, /* cancelable */
790
g_warning("Unable to get instances of job '%s': %s", jobname, error->message);
795
GVariant * instance_list = g_variant_get_child_value(instance_tuple, 0);
796
g_variant_unref(instance_tuple);
798
GVariantIter instance_iter;
799
g_variant_iter_init(&instance_iter, instance_list);
800
const gchar * instance_path = NULL;
802
while (g_variant_iter_loop(&instance_iter, "&o", &instance_path)) {
803
GVariant * props_tuple = g_dbus_connection_call_sync(con,
804
DBUS_SERVICE_UPSTART,
806
"org.freedesktop.DBus.Properties",
808
g_variant_new("(s)", DBUS_INTERFACE_UPSTART_INSTANCE),
809
G_VARIANT_TYPE("(a{sv})"),
810
G_DBUS_CALL_FLAGS_NONE,
811
-1, /* timeout: default */
812
NULL, /* cancelable */
816
g_warning("Unable to name of instance '%s': %s", instance_path, error->message);
822
GVariant * props_dict = g_variant_get_child_value(props_tuple, 0);
824
func(con, props_dict, user_data);
826
g_variant_unref(props_dict);
827
g_variant_unref(props_tuple);
831
g_variant_unref(instance_list);
836
gboolean truncate_legacy;
837
const gchar * jobname;
841
apps_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data)
843
GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING);
848
apps_for_job_t * data = (apps_for_job_t *)user_data;
849
gchar * instance_name = g_variant_dup_string(namev, NULL);
850
g_variant_unref(namev);
852
if (data->truncate_legacy && g_strcmp0(data->jobname, "application-legacy") == 0) {
853
gchar * last_dash = g_strrstr(instance_name, "-");
854
if (last_dash != NULL) {
859
g_array_append_val(data->apps, instance_name);
526
862
/* Get all the instances for a given job name */
528
apps_for_job (NihDBusProxy * upstart, const gchar * name, GArray * apps, gboolean truncate_legacy)
864
apps_for_job (GDBusConnection * con, const gchar * jobname, GArray * apps, gboolean truncate_legacy)
530
nih_local char * job_path = NULL;
531
if (upstart_get_job_by_name_sync(NULL, upstart, name, &job_path) != 0) {
532
g_warning("Unable to find job '%s'", name);
536
nih_local NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection,
541
if (job_proxy == NULL) {
542
g_warning("Unable to build proxy to Job '%s'", name);
546
nih_local char ** instances;
547
if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) {
548
NihError * error = nih_error_get();
549
g_warning("Unable to get instances for job '%s': %s", name, error->message);
555
for (jobnum = 0; instances[jobnum] != NULL; jobnum++) {
556
NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection,
561
nih_local char * instance_name = NULL;
562
if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) {
563
gchar * dup = g_strdup(instance_name);
565
if (truncate_legacy && g_strcmp0(name, "application-legacy") == 0) {
566
gchar * last_dash = g_strrstr(dup, "-");
567
if (last_dash != NULL) {
572
g_array_append_val(apps, dup);
574
g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], name);
577
nih_unref(instance_proxy, NULL);
866
apps_for_job_t data = {
869
.truncate_legacy = truncate_legacy
872
foreach_job_instance(con, jobname, apps_for_job_instance, &data);
582
876
upstart_app_launch_list_running_apps (void)
584
NihDBusProxy * proxy = NULL;
586
proxy = nih_proxy_create();
588
return g_new0(gchar *, 1);
878
GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
879
g_return_val_if_fail(con != NULL, g_new0(gchar *, 1));
591
881
GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *));
593
apps_for_job(proxy, "application-legacy", apps, TRUE);
594
apps_for_job(proxy, "application-click", apps, FALSE);
883
apps_for_job(con, "application-legacy", apps, TRUE);
884
apps_for_job(con, "application-click", apps, FALSE);
596
nih_unref(proxy, NULL);
598
888
return (gchar **)g_array_free(apps, FALSE);
894
const gchar * jobname;
898
pid_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data)
900
GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING);
905
pid_for_job_t * data = (pid_for_job_t *)user_data;
906
gchar * instance_name = g_variant_dup_string(namev, NULL);
907
g_variant_unref(namev);
909
if (g_strcmp0(data->jobname, "application-legacy") == 0) {
910
gchar * last_dash = g_strrstr(instance_name, "-");
911
if (last_dash != NULL) {
916
if (g_strcmp0(instance_name, data->appid) == 0) {
917
GVariant * processv = g_variant_lookup_value(props_dict, "processes", G_VARIANT_TYPE("a(si)"));
919
if (processv != NULL) {
920
if (g_variant_n_children(processv) > 0) {
921
GVariant * first_entry = g_variant_get_child_value(processv, 0);
922
GVariant * pidv = g_variant_get_child_value(first_entry, 1);
924
data->pid = g_variant_get_int32(pidv);
926
g_variant_unref(pidv);
927
g_variant_unref(first_entry);
930
g_variant_unref(processv);
934
g_free(instance_name);
601
937
/* Look for the app for a job */
603
pid_for_job (NihDBusProxy * upstart, const gchar * job, const gchar * appid)
939
pid_for_job (GDBusConnection * con, const gchar * jobname, const gchar * appid)
605
nih_local char * job_path = NULL;
606
if (upstart_get_job_by_name_sync(NULL, upstart, job, &job_path) != 0) {
607
g_warning("Unable to find job '%s'", job);
611
NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection,
616
if (job_proxy == NULL) {
617
g_warning("Unable to build proxy to Job '%s'", job);
621
nih_local char ** instances;
622
if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) {
623
g_warning("Unable to get instances for job '%s'", job);
624
nih_unref(job_proxy, NULL);
630
for (jobnum = 0; instances[jobnum] != NULL && pid == 0; jobnum++) {
631
NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection,
636
nih_local char * instance_name = NULL;
637
if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) {
638
if (g_strcmp0(job, "application-legacy") == 0) {
639
gchar * last_dash = g_strrstr(instance_name, "-");
640
if (last_dash != NULL) {
645
g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], job);
648
if (g_strcmp0(instance_name, appid) == 0) {
649
nih_local JobProcessesElement ** elements;
650
if (job_get_processes_sync(NULL, instance_proxy, &elements) == 0) {
651
pid = elements[0]->item1;
655
nih_unref(instance_proxy, NULL);
658
nih_unref(job_proxy, NULL);
941
pid_for_job_t data = {
947
foreach_job_instance(con, jobname, pid_for_job_instance, &data);
664
953
upstart_app_launch_get_primary_pid (const gchar * appid)
666
NihDBusProxy * proxy = NULL;
955
g_return_val_if_fail(appid != NULL, 0);
668
proxy = nih_proxy_create();
957
GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
958
g_return_val_if_fail(con != NULL, 0);
676
pid = pid_for_job(proxy, "application-legacy", appid);
963
pid = pid_for_job(con, "application-legacy", appid);
680
pid = pid_for_job(proxy, "application-click", appid);
967
pid = pid_for_job(con, "application-click", appid);
683
nih_unref(proxy, NULL);