1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* activation.c Activation of services
4 * Copyright (C) 2003 CodeFactory AB
5 * Copyright (C) 2003 Red Hat, Inc.
6 * Copyright (C) 2004 Imendio HB
8 * Licensed under the Academic Free License version 2.1
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "activation.h"
28 #include "activation-exit-codes.h"
29 #include "desktop-file.h"
34 #include <dbus/dbus-internals.h>
35 #include <dbus/dbus-hash.h>
36 #include <dbus/dbus-list.h>
37 #include <dbus/dbus-shell.h>
38 #include <dbus/dbus-spawn.h>
39 #include <dbus/dbus-timeout.h>
40 #include <dbus/dbus-sysdeps.h>
48 DBusHashTable *entries;
49 DBusHashTable *pending_activations;
52 int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
53 * i.e. number of pending activation requests, not pending
56 DBusHashTable *directories;
57 DBusHashTable *environment;
64 DBusHashTable *entries;
65 } BusServiceDirectory;
73 char *systemd_service;
75 BusServiceDirectory *s_dir;
79 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
81 struct BusPendingActivationEntry
83 DBusMessage *activation_message;
84 DBusConnection *connection;
86 dbus_bool_t auto_activation;
92 BusActivation *activation;
95 char *systemd_service;
98 DBusBabysitter *babysitter;
100 unsigned int timeout_added : 1;
101 } BusPendingActivation;
104 static BusServiceDirectory *
105 bus_service_directory_ref (BusServiceDirectory *dir)
107 _dbus_assert (dir->refcount);
116 bus_service_directory_unref (BusServiceDirectory *dir)
121 _dbus_assert (dir->refcount > 0);
124 if (dir->refcount > 0)
128 _dbus_hash_table_unref (dir->entries);
130 dbus_free (dir->dir_c);
135 bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
137 if (entry->activation_message)
138 dbus_message_unref (entry->activation_message);
140 if (entry->connection)
141 dbus_connection_unref (entry->connection);
147 handle_timeout_callback (DBusTimeout *timeout,
150 BusPendingActivation *pending_activation = data;
152 while (!dbus_timeout_handle (pending_activation->timeout))
153 _dbus_wait_for_memory ();
156 static BusPendingActivation *
157 bus_pending_activation_ref (BusPendingActivation *pending_activation)
159 _dbus_assert (pending_activation->refcount > 0);
160 pending_activation->refcount += 1;
162 return pending_activation;
166 bus_pending_activation_unref (BusPendingActivation *pending_activation)
170 if (pending_activation == NULL) /* hash table requires this */
173 _dbus_assert (pending_activation->refcount > 0);
174 pending_activation->refcount -= 1;
176 if (pending_activation->refcount > 0)
179 if (pending_activation->timeout_added)
181 _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
182 pending_activation->timeout,
183 handle_timeout_callback, pending_activation);
184 pending_activation->timeout_added = FALSE;
187 if (pending_activation->timeout)
188 _dbus_timeout_unref (pending_activation->timeout);
190 if (pending_activation->babysitter)
192 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
194 pending_activation->babysitter,
196 _dbus_assert_not_reached ("setting watch functions to NULL failed");
198 _dbus_babysitter_unref (pending_activation->babysitter);
201 dbus_free (pending_activation->service_name);
202 dbus_free (pending_activation->exec);
203 dbus_free (pending_activation->systemd_service);
205 link = _dbus_list_get_first_link (&pending_activation->entries);
209 BusPendingActivationEntry *entry = link->data;
211 bus_pending_activation_entry_free (entry);
213 link = _dbus_list_get_next_link (&pending_activation->entries, link);
215 _dbus_list_clear (&pending_activation->entries);
217 pending_activation->activation->n_pending_activations -=
218 pending_activation->n_entries;
220 _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
222 dbus_free (pending_activation);
225 static BusActivationEntry *
226 bus_activation_entry_ref (BusActivationEntry *entry)
228 _dbus_assert (entry->refcount > 0);
235 bus_activation_entry_unref (BusActivationEntry *entry)
237 if (entry == NULL) /* hash table requires this */
240 _dbus_assert (entry->refcount > 0);
243 if (entry->refcount > 0)
246 dbus_free (entry->name);
247 dbus_free (entry->exec);
248 dbus_free (entry->user);
249 dbus_free (entry->filename);
250 dbus_free (entry->systemd_service);
256 update_desktop_file_entry (BusActivation *activation,
257 BusServiceDirectory *s_dir,
258 DBusString *filename,
259 BusDesktopFile *desktop_file,
262 char *name, *exec, *user, *exec_tmp, *systemd_service;
263 BusActivationEntry *entry;
265 DBusString file_path;
268 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
275 systemd_service = NULL;
277 dbus_error_init (&tmp_error);
279 if (!_dbus_string_init (&file_path))
285 if (!_dbus_string_append (&file_path, s_dir->dir_c) ||
286 !_dbus_concat_dir_and_file (&file_path, filename))
292 if (!_dbus_stat (&file_path, &stat_buf, NULL))
294 dbus_set_error (error, DBUS_ERROR_FAILED,
295 "Can't stat the service file\n");
299 if (!bus_desktop_file_get_string (desktop_file,
300 DBUS_SERVICE_SECTION,
306 if (!bus_desktop_file_get_string (desktop_file,
307 DBUS_SERVICE_SECTION,
313 exec = _dbus_strdup (_dbus_replace_install_prefix (exec_tmp));
314 dbus_free (exec_tmp);
317 /* user is not _required_ unless we are using system activation */
318 if (!bus_desktop_file_get_string (desktop_file,
319 DBUS_SERVICE_SECTION,
323 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
324 /* if we got OOM, then exit */
325 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
327 dbus_move_error (&tmp_error, error);
332 /* if we have error because we didn't find anything then continue */
333 dbus_error_free (&tmp_error);
338 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
340 /* systemd service is never required */
341 if (!bus_desktop_file_get_string (desktop_file,
342 DBUS_SERVICE_SECTION,
343 DBUS_SERVICE_SYSTEMD_SERVICE,
344 &systemd_service, &tmp_error))
346 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
347 /* if we got OOM, then exit */
348 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
350 dbus_move_error (&tmp_error, error);
355 /* if we have error because we didn't find anything then continue */
356 dbus_error_free (&tmp_error);
357 dbus_free (systemd_service);
358 systemd_service = NULL;
362 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
364 entry = _dbus_hash_table_lookup_string (s_dir->entries,
365 _dbus_string_get_const_data (filename));
367 if (entry == NULL) /* New file */
369 /* FIXME we need a better-defined algorithm for which service file to
370 * pick than "whichever one is first in the directory listing"
372 if (_dbus_hash_table_lookup_string (activation->entries, name))
374 dbus_set_error (error, DBUS_ERROR_FAILED,
375 "Service %s already exists in activation entry list\n", name);
379 entry = dbus_new0 (BusActivationEntry, 1);
389 entry->systemd_service = systemd_service;
392 entry->s_dir = s_dir;
393 entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
394 if (!entry->filename)
400 if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
406 if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry)))
408 /* Revert the insertion in the entries table */
409 _dbus_hash_table_remove_string (activation->entries, entry->name);
414 _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
416 else /* Just update the entry */
418 bus_activation_entry_ref (entry);
419 _dbus_hash_table_remove_string (activation->entries, entry->name);
421 if (_dbus_hash_table_lookup_string (activation->entries, name))
423 _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n",
424 name, _dbus_string_get_const_data (&file_path));
428 dbus_free (entry->name);
429 dbus_free (entry->exec);
430 dbus_free (entry->user);
431 dbus_free (entry->systemd_service);
432 entry->systemd_service = systemd_service;
436 if (!_dbus_hash_table_insert_string (activation->entries,
437 entry->name, bus_activation_entry_ref(entry)))
440 /* Also remove path to entries hash since we want this in sync with
441 * the entries hash table */
442 _dbus_hash_table_remove_string (entry->s_dir->entries,
444 bus_activation_entry_unref (entry);
449 entry->mtime = stat_buf.mtime;
451 _dbus_string_free (&file_path);
452 bus_activation_entry_unref (entry);
459 dbus_free (systemd_service);
460 _dbus_string_free (&file_path);
463 bus_activation_entry_unref (entry);
469 check_service_file (BusActivation *activation,
470 BusActivationEntry *entry,
471 BusActivationEntry **updated_entry,
476 BusActivationEntry *tmp_entry;
477 DBusString file_path;
483 _dbus_string_init_const (&filename, entry->filename);
485 if (!_dbus_string_init (&file_path))
491 if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) ||
492 !_dbus_concat_dir_and_file (&file_path, &filename))
499 if (!_dbus_stat (&file_path, &stat_buf, NULL))
501 _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n",
502 _dbus_string_get_const_data (&file_path));
504 _dbus_hash_table_remove_string (activation->entries, entry->name);
505 _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename);
513 if (stat_buf.mtime > entry->mtime)
515 BusDesktopFile *desktop_file;
518 dbus_error_init (&tmp_error);
520 desktop_file = bus_desktop_file_load (&file_path, &tmp_error);
521 if (desktop_file == NULL)
523 _dbus_verbose ("Could not load %s: %s\n",
524 _dbus_string_get_const_data (&file_path),
526 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
528 dbus_move_error (&tmp_error, error);
532 dbus_error_free (&tmp_error);
537 /* @todo We can return OOM or a DBUS_ERROR_FAILED error
538 * Handle these both better
540 if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error))
542 bus_desktop_file_free (desktop_file);
543 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
545 dbus_move_error (&tmp_error, error);
549 dbus_error_free (&tmp_error);
554 bus_desktop_file_free (desktop_file);
560 _dbus_string_free (&file_path);
562 if (updated_entry != NULL)
563 *updated_entry = tmp_entry;
568 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
569 * hash entries it already added.
572 update_directory (BusActivation *activation,
573 BusServiceDirectory *s_dir,
577 DBusString dir, filename;
578 BusDesktopFile *desktop_file;
581 BusActivationEntry *entry;
582 DBusString full_path;
584 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
589 _dbus_string_init_const (&dir, s_dir->dir_c);
591 if (!_dbus_string_init (&filename))
597 if (!_dbus_string_init (&full_path))
600 _dbus_string_free (&filename);
606 /* from this point it's safe to "goto out" */
608 iter = _dbus_directory_open (&dir, error);
611 _dbus_verbose ("Failed to open directory %s: %s\n",
613 error ? error->message : "unknown");
617 /* Now read the files */
618 dbus_error_init (&tmp_error);
619 while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
621 _dbus_assert (!dbus_error_is_set (&tmp_error));
623 _dbus_string_set_length (&full_path, 0);
625 if (!_dbus_string_ends_with_c_str (&filename, ".service"))
627 _dbus_verbose ("Skipping non-.service file %s\n",
628 _dbus_string_get_const_data (&filename));
632 entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename));
633 if (entry) /* Already has this service file in the cache */
635 if (!check_service_file (activation, entry, NULL, error))
641 if (!_dbus_string_append (&full_path, s_dir->dir_c) ||
642 !_dbus_concat_dir_and_file (&full_path, &filename))
649 desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
650 if (desktop_file == NULL)
652 _dbus_verbose ("Could not load %s: %s\n",
653 _dbus_string_get_const_data (&full_path),
656 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
658 dbus_move_error (&tmp_error, error);
662 dbus_error_free (&tmp_error);
666 /* @todo We can return OOM or a DBUS_ERROR_FAILED error
667 * Handle these both better
669 if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error))
671 bus_desktop_file_free (desktop_file);
674 _dbus_verbose ("Could not add %s to activation entry list: %s\n",
675 _dbus_string_get_const_data (&full_path), tmp_error.message);
677 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
679 dbus_move_error (&tmp_error, error);
683 dbus_error_free (&tmp_error);
688 bus_desktop_file_free (desktop_file);
694 if (dbus_error_is_set (&tmp_error))
696 dbus_move_error (&tmp_error, error);
704 _DBUS_ASSERT_ERROR_IS_SET (error);
706 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
709 _dbus_directory_close (iter);
710 _dbus_string_free (&filename);
711 _dbus_string_free (&full_path);
717 populate_environment (BusActivation *activation)
723 dbus_bool_t retval = FALSE;
725 environment = _dbus_get_environment ();
727 if (environment == NULL)
730 if (!_dbus_string_init (&key))
732 dbus_free_string_array (environment);
736 if (!_dbus_string_init (&value))
738 _dbus_string_free (&key);
739 dbus_free_string_array (environment);
743 for (i = 0; environment[i] != NULL; i++)
745 if (!_dbus_string_append (&key, environment[i]))
748 if (_dbus_string_split_on_byte (&key, '=', &value))
750 char *hash_key, *hash_value;
752 if (!_dbus_string_steal_data (&key, &hash_key))
755 if (!_dbus_string_steal_data (&value, &hash_value))
758 if (!_dbus_hash_table_insert_string (activation->environment,
759 hash_key, hash_value))
762 _dbus_string_set_length (&key, 0);
763 _dbus_string_set_length (&value, 0);
766 if (environment[i] != NULL)
772 _dbus_string_free (&key);
773 _dbus_string_free (&value);
774 dbus_free_string_array (environment);
780 bus_activation_reload (BusActivation *activation,
781 const DBusString *address,
782 DBusList **directories,
788 if (activation->server_address != NULL)
789 dbus_free (activation->server_address);
790 if (!_dbus_string_copy_data (address, &activation->server_address))
796 if (activation->entries != NULL)
797 _dbus_hash_table_unref (activation->entries);
798 activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
799 (DBusFreeFunction)bus_activation_entry_unref);
800 if (activation->entries == NULL)
806 if (activation->directories != NULL)
807 _dbus_hash_table_unref (activation->directories);
808 activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
809 (DBusFreeFunction)bus_service_directory_unref);
811 if (activation->directories == NULL)
817 link = _dbus_list_get_first_link (directories);
820 BusServiceDirectory *s_dir;
822 dir = _dbus_strdup ((const char *) link->data);
829 s_dir = dbus_new0 (BusServiceDirectory, 1);
840 s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
841 (DBusFreeFunction)bus_activation_entry_unref);
845 bus_service_directory_unref (s_dir);
850 if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
852 bus_service_directory_unref (s_dir);
857 /* only fail on OOM, it is ok if we can't read the directory */
858 if (!update_directory (activation, s_dir, error))
860 if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
863 dbus_error_free (error);
866 link = _dbus_list_get_next_link (directories, link);
875 bus_activation_new (BusContext *context,
876 const DBusString *address,
877 DBusList **directories,
880 BusActivation *activation;
884 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
886 activation = dbus_new0 (BusActivation, 1);
887 if (activation == NULL)
893 activation->refcount = 1;
894 activation->context = context;
895 activation->n_pending_activations = 0;
897 if (!bus_activation_reload (activation, address, directories, error))
900 /* Initialize this hash table once, we don't want to lose pending
901 * activations on reload. */
902 activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
903 (DBusFreeFunction)bus_pending_activation_unref);
905 if (activation->pending_activations == NULL)
911 activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING,
912 (DBusFreeFunction) dbus_free,
913 (DBusFreeFunction) dbus_free);
915 if (activation->environment == NULL)
921 if (!populate_environment (activation))
930 bus_activation_unref (activation);
935 bus_activation_ref (BusActivation *activation)
937 _dbus_assert (activation->refcount > 0);
939 activation->refcount += 1;
945 bus_activation_unref (BusActivation *activation)
947 _dbus_assert (activation->refcount > 0);
949 activation->refcount -= 1;
951 if (activation->refcount > 0)
954 dbus_free (activation->server_address);
955 if (activation->entries)
956 _dbus_hash_table_unref (activation->entries);
957 if (activation->pending_activations)
958 _dbus_hash_table_unref (activation->pending_activations);
959 if (activation->directories)
960 _dbus_hash_table_unref (activation->directories);
961 if (activation->environment)
962 _dbus_hash_table_unref (activation->environment);
964 dbus_free (activation);
968 add_bus_environment (BusActivation *activation,
973 if (!bus_activation_set_environment_variable (activation,
974 "DBUS_STARTER_ADDRESS",
975 activation->server_address,
979 type = bus_context_get_type (activation->context);
982 if (!bus_activation_set_environment_variable (activation,
983 "DBUS_STARTER_BUS_TYPE", type,
987 if (strcmp (type, "session") == 0)
989 if (!bus_activation_set_environment_variable (activation,
990 "DBUS_SESSION_BUS_ADDRESS",
991 activation->server_address,
995 else if (strcmp (type, "system") == 0)
997 if (!bus_activation_set_environment_variable (activation,
998 "DBUS_SYSTEM_BUS_ADDRESS",
999 activation->server_address,
1010 BusPendingActivation *pending_activation;
1011 DBusPreallocatedHash *hash_entry;
1012 } RestorePendingData;
1015 restore_pending (void *data)
1017 RestorePendingData *d = data;
1019 _dbus_assert (d->pending_activation != NULL);
1020 _dbus_assert (d->hash_entry != NULL);
1022 _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
1023 d->pending_activation->service_name,
1024 d->pending_activation->timeout_added);
1026 _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
1028 d->pending_activation->service_name, d->pending_activation);
1030 bus_pending_activation_ref (d->pending_activation);
1032 d->hash_entry = NULL;
1036 free_pending_restore_data (void *data)
1038 RestorePendingData *d = data;
1041 _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
1044 bus_pending_activation_unref (d->pending_activation);
1050 add_restore_pending_to_transaction (BusTransaction *transaction,
1051 BusPendingActivation *pending_activation)
1053 RestorePendingData *d;
1055 d = dbus_new (RestorePendingData, 1);
1059 d->pending_activation = pending_activation;
1060 d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
1062 bus_pending_activation_ref (d->pending_activation);
1064 if (d->hash_entry == NULL ||
1065 !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
1066 free_pending_restore_data))
1068 free_pending_restore_data (d);
1072 _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
1078 bus_activation_service_created (BusActivation *activation,
1079 const char *service_name,
1080 BusTransaction *transaction,
1083 BusPendingActivation *pending_activation;
1084 DBusMessage *message;
1087 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1089 /* Check if it's a pending activation */
1090 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1092 if (!pending_activation)
1095 link = _dbus_list_get_first_link (&pending_activation->entries);
1096 while (link != NULL)
1098 BusPendingActivationEntry *entry = link->data;
1099 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1101 if (dbus_connection_get_is_connected (entry->connection))
1103 /* Only send activation replies to regular activation requests. */
1104 if (!entry->auto_activation)
1106 dbus_uint32_t result;
1108 message = dbus_message_new_method_return (entry->activation_message);
1111 BUS_SET_OOM (error);
1115 result = DBUS_START_REPLY_SUCCESS;
1117 if (!dbus_message_append_args (message,
1118 DBUS_TYPE_UINT32, &result,
1121 dbus_message_unref (message);
1122 BUS_SET_OOM (error);
1126 if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
1128 dbus_message_unref (message);
1129 BUS_SET_OOM (error);
1133 dbus_message_unref (message);
1147 bus_activation_send_pending_auto_activation_messages (BusActivation *activation,
1148 BusService *service,
1149 BusTransaction *transaction,
1152 BusPendingActivation *pending_activation;
1155 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1157 /* Check if it's a pending activation */
1158 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
1159 bus_service_get_name (service));
1161 if (!pending_activation)
1164 link = _dbus_list_get_first_link (&pending_activation->entries);
1165 while (link != NULL)
1167 BusPendingActivationEntry *entry = link->data;
1168 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1170 if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
1172 DBusConnection *addressed_recipient;
1174 addressed_recipient = bus_service_get_primary_owners_connection (service);
1176 /* Resume dispatching where we left off in bus_dispatch() */
1177 if (!bus_dispatch_matches (transaction,
1179 addressed_recipient,
1180 entry->activation_message, error))
1187 if (!add_restore_pending_to_transaction (transaction, pending_activation))
1189 _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
1190 BUS_SET_OOM (error);
1194 _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
1203 * FIXME @todo the error messages here would ideally be preallocated
1204 * so we don't need to allocate memory to send them.
1205 * Using the usual tactic, prealloc an OOM message, then
1206 * if we can't alloc the real error send the OOM error instead.
1209 try_send_activation_failure (BusPendingActivation *pending_activation,
1210 const DBusError *how)
1212 BusActivation *activation;
1214 BusTransaction *transaction;
1216 activation = pending_activation->activation;
1218 transaction = bus_transaction_new (activation->context);
1219 if (transaction == NULL)
1222 link = _dbus_list_get_first_link (&pending_activation->entries);
1223 while (link != NULL)
1225 BusPendingActivationEntry *entry = link->data;
1226 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1228 if (dbus_connection_get_is_connected (entry->connection))
1230 if (!bus_transaction_send_error_reply (transaction,
1233 entry->activation_message))
1240 bus_transaction_execute_and_free (transaction);
1246 bus_transaction_cancel_and_free (transaction);
1251 * Free the pending activation and send an error message to all the
1252 * connections that were waiting for it.
1255 pending_activation_failed (BusPendingActivation *pending_activation,
1256 const DBusError *how)
1258 /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
1259 while (!try_send_activation_failure (pending_activation, how))
1260 _dbus_wait_for_memory ();
1262 /* Destroy this pending activation */
1263 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1264 pending_activation->service_name);
1268 * Depending on the exit code of the helper, set the error accordingly
1271 handle_servicehelper_exit_error (int exit_code,
1276 case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
1277 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1278 "Launcher could not run (out of memory)");
1280 case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
1281 dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
1282 "Failed to setup environment correctly");
1284 case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
1285 dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
1286 "Bus name is not valid or missing");
1288 case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
1289 dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
1290 "Bus name not found in system service directory");
1292 case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
1293 dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1294 "The permission of the setuid helper is not correct");
1296 case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
1297 dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1298 "The service file is incorrect or does not have all required attributes");
1300 case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
1301 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
1302 "Cannot launch daemon, file not found or permissions invalid");
1304 case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
1305 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1306 "Invalid arguments to command line");
1308 case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
1309 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
1310 "Launched child was signaled, it probably crashed");
1313 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
1314 "Launch helper exited with unknown return code %i", exit_code);
1320 babysitter_watch_callback (DBusWatch *watch,
1321 unsigned int condition,
1324 BusPendingActivation *pending_activation = data;
1326 DBusBabysitter *babysitter;
1327 dbus_bool_t uses_servicehelper;
1329 babysitter = pending_activation->babysitter;
1331 _dbus_babysitter_ref (babysitter);
1333 retval = dbus_watch_handle (watch, condition);
1335 /* There are two major cases here; are we the system bus or the session? Here this
1336 * is distinguished by whether or not we use a setuid helper launcher. With the launch helper,
1337 * some process exit codes are meaningful, processed by handle_servicehelper_exit_error.
1339 * In both cases though, just ignore when a process exits with status 0; it's possible for
1340 * a program to (misguidedly) "daemonize", and that appears to us as an exit. This closes a race
1341 * condition between this code and the child process claiming the bus name.
1343 uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL;
1345 /* FIXME this is broken in the same way that
1346 * connection watches used to be; there should be
1347 * a separate callback for status change, instead
1348 * of doing "if we handled a watch status might
1351 * Fixing this lets us move dbus_watch_handle
1352 * calls into dbus-mainloop.c
1354 if (_dbus_babysitter_get_child_exited (babysitter))
1358 dbus_bool_t activation_failed;
1361 dbus_error_init (&error);
1363 _dbus_babysitter_set_child_exit_error (babysitter, &error);
1365 /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an
1367 if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)
1368 && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
1370 activation_failed = exit_code != 0;
1372 dbus_error_free(&error);
1374 if (activation_failed)
1376 if (uses_servicehelper)
1377 handle_servicehelper_exit_error (exit_code, &error);
1379 _dbus_babysitter_set_child_exit_error (babysitter, &error);
1384 activation_failed = TRUE;
1387 if (activation_failed)
1389 /* Destroy all pending activations with the same exec */
1390 _dbus_hash_iter_init (pending_activation->activation->pending_activations,
1392 while (_dbus_hash_iter_next (&iter))
1394 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1396 if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
1397 pending_activation_failed (p, &error);
1400 /* Destroys the pending activation */
1401 pending_activation_failed (pending_activation, &error);
1403 dbus_error_free (&error);
1407 _dbus_babysitter_unref (babysitter);
1413 add_babysitter_watch (DBusWatch *watch,
1416 BusPendingActivation *pending_activation = data;
1418 return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
1419 watch, babysitter_watch_callback, pending_activation,
1424 remove_babysitter_watch (DBusWatch *watch,
1427 BusPendingActivation *pending_activation = data;
1429 _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
1430 watch, babysitter_watch_callback, pending_activation);
1434 pending_activation_timed_out (void *data)
1436 BusPendingActivation *pending_activation = data;
1439 /* Kill the spawned process, since it sucks
1440 * (not sure this is what we want to do, but
1441 * may as well try it for now)
1443 if (pending_activation->babysitter)
1444 _dbus_babysitter_kill_child (pending_activation->babysitter);
1446 dbus_error_init (&error);
1448 dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
1449 "Activation of %s timed out",
1450 pending_activation->service_name);
1452 pending_activation_failed (pending_activation, &error);
1454 dbus_error_free (&error);
1460 cancel_pending (void *data)
1462 BusPendingActivation *pending_activation = data;
1464 _dbus_verbose ("Canceling pending activation of %s\n",
1465 pending_activation->service_name);
1467 if (pending_activation->babysitter)
1468 _dbus_babysitter_kill_child (pending_activation->babysitter);
1470 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1471 pending_activation->service_name);
1475 free_pending_cancel_data (void *data)
1477 BusPendingActivation *pending_activation = data;
1479 bus_pending_activation_unref (pending_activation);
1483 add_cancel_pending_to_transaction (BusTransaction *transaction,
1484 BusPendingActivation *pending_activation)
1486 if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
1488 free_pending_cancel_data))
1491 bus_pending_activation_ref (pending_activation);
1493 _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
1499 update_service_cache (BusActivation *activation, DBusError *error)
1503 _dbus_hash_iter_init (activation->directories, &iter);
1504 while (_dbus_hash_iter_next (&iter))
1506 DBusError tmp_error;
1507 BusServiceDirectory *s_dir;
1509 s_dir = _dbus_hash_iter_get_value (&iter);
1511 dbus_error_init (&tmp_error);
1512 if (!update_directory (activation, s_dir, &tmp_error))
1514 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
1516 dbus_move_error (&tmp_error, error);
1520 dbus_error_free (&tmp_error);
1528 static BusActivationEntry *
1529 activation_find_entry (BusActivation *activation,
1530 const char *service_name,
1533 BusActivationEntry *entry;
1535 entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
1538 if (!update_service_cache (activation, error))
1541 entry = _dbus_hash_table_lookup_string (activation->entries,
1546 BusActivationEntry *updated_entry;
1548 if (!check_service_file (activation, entry, &updated_entry, error))
1551 entry = updated_entry;
1556 dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
1557 "The name %s was not provided by any .service files",
1566 bus_activation_get_environment (BusActivation *activation)
1573 length = _dbus_hash_table_get_n_entries (activation->environment);
1575 environment = dbus_new0 (char *, length + 1);
1577 if (environment == NULL)
1581 _dbus_hash_iter_init (activation->environment, &iter);
1583 if (!_dbus_string_init (&entry))
1585 dbus_free_string_array (environment);
1589 while (_dbus_hash_iter_next (&iter))
1591 const char *key, *value;
1593 key = (const char *) _dbus_hash_iter_get_string_key (&iter);
1594 value = (const char *) _dbus_hash_iter_get_value (&iter);
1596 if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
1599 if (!_dbus_string_steal_data (&entry, environment + i))
1604 _dbus_string_free (&entry);
1608 dbus_free_string_array (environment);
1616 bus_activation_set_environment_variable (BusActivation *activation,
1628 hash_key = _dbus_strdup (key);
1630 if (hash_key == NULL)
1633 hash_value = _dbus_strdup (value);
1635 if (hash_value == NULL)
1638 if (!_dbus_hash_table_insert_string (activation->environment,
1639 hash_key, hash_value))
1644 if (retval == FALSE)
1646 dbus_free (hash_key);
1647 dbus_free (hash_value);
1648 BUS_SET_OOM (error);
1655 bus_activation_activate_service (BusActivation *activation,
1656 DBusConnection *connection,
1657 BusTransaction *transaction,
1658 dbus_bool_t auto_activation,
1659 DBusMessage *activation_message,
1660 const char *service_name,
1663 BusActivationEntry *entry;
1664 BusPendingActivation *pending_activation;
1665 BusPendingActivationEntry *pending_activation_entry;
1666 DBusMessage *message;
1667 DBusString service_str;
1668 const char *servicehelper;
1674 dbus_bool_t activated;
1679 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1681 if (activation->n_pending_activations >=
1682 bus_context_get_max_pending_activations (activation->context))
1684 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1685 "The maximum number of pending activations has been reached, activation of %s failed",
1690 entry = activation_find_entry (activation, service_name, error);
1694 /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
1695 * call us if the service is already active.
1697 if (!auto_activation)
1699 /* Check if the service is active */
1700 _dbus_string_init_const (&service_str, service_name);
1701 if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
1703 dbus_uint32_t result;
1705 _dbus_verbose ("Service \"%s\" is already active\n", service_name);
1707 message = dbus_message_new_method_return (activation_message);
1711 _dbus_verbose ("No memory to create reply to activate message\n");
1712 BUS_SET_OOM (error);
1716 result = DBUS_START_REPLY_ALREADY_RUNNING;
1718 if (!dbus_message_append_args (message,
1719 DBUS_TYPE_UINT32, &result,
1722 _dbus_verbose ("No memory to set args of reply to activate message\n");
1723 BUS_SET_OOM (error);
1724 dbus_message_unref (message);
1728 retval = bus_transaction_send_from_driver (transaction, connection, message);
1729 dbus_message_unref (message);
1732 _dbus_verbose ("Failed to send reply\n");
1733 BUS_SET_OOM (error);
1740 pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
1741 if (!pending_activation_entry)
1743 _dbus_verbose ("Failed to create pending activation entry\n");
1744 BUS_SET_OOM (error);
1748 pending_activation_entry->auto_activation = auto_activation;
1750 pending_activation_entry->activation_message = activation_message;
1751 dbus_message_ref (activation_message);
1752 pending_activation_entry->connection = connection;
1753 dbus_connection_ref (connection);
1755 /* Check if the service is being activated */
1756 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1757 if (pending_activation)
1759 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1761 _dbus_verbose ("Failed to append a new entry to pending activation\n");
1763 BUS_SET_OOM (error);
1764 bus_pending_activation_entry_free (pending_activation_entry);
1768 pending_activation->n_entries += 1;
1769 pending_activation->activation->n_pending_activations += 1;
1773 pending_activation = dbus_new0 (BusPendingActivation, 1);
1774 if (!pending_activation)
1776 _dbus_verbose ("Failed to create pending activation\n");
1778 BUS_SET_OOM (error);
1779 bus_pending_activation_entry_free (pending_activation_entry);
1783 pending_activation->activation = activation;
1784 pending_activation->refcount = 1;
1786 pending_activation->service_name = _dbus_strdup (service_name);
1787 if (!pending_activation->service_name)
1789 _dbus_verbose ("Failed to copy service name for pending activation\n");
1791 BUS_SET_OOM (error);
1792 bus_pending_activation_unref (pending_activation);
1793 bus_pending_activation_entry_free (pending_activation_entry);
1797 pending_activation->exec = _dbus_strdup (entry->exec);
1798 if (!pending_activation->exec)
1800 _dbus_verbose ("Failed to copy service exec for pending activation\n");
1801 BUS_SET_OOM (error);
1802 bus_pending_activation_unref (pending_activation);
1803 bus_pending_activation_entry_free (pending_activation_entry);
1807 if (entry->systemd_service)
1809 pending_activation->systemd_service = _dbus_strdup (entry->systemd_service);
1810 if (!pending_activation->systemd_service)
1812 _dbus_verbose ("Failed to copy systemd service for pending activation\n");
1813 BUS_SET_OOM (error);
1814 bus_pending_activation_unref (pending_activation);
1815 bus_pending_activation_entry_free (pending_activation_entry);
1820 pending_activation->timeout =
1821 _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
1822 pending_activation_timed_out,
1825 if (!pending_activation->timeout)
1827 _dbus_verbose ("Failed to create timeout for pending activation\n");
1829 BUS_SET_OOM (error);
1830 bus_pending_activation_unref (pending_activation);
1831 bus_pending_activation_entry_free (pending_activation_entry);
1835 if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
1836 pending_activation->timeout,
1837 handle_timeout_callback,
1841 _dbus_verbose ("Failed to add timeout for pending activation\n");
1843 BUS_SET_OOM (error);
1844 bus_pending_activation_unref (pending_activation);
1845 bus_pending_activation_entry_free (pending_activation_entry);
1849 pending_activation->timeout_added = TRUE;
1851 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1853 _dbus_verbose ("Failed to add entry to just-created pending activation\n");
1855 BUS_SET_OOM (error);
1856 bus_pending_activation_unref (pending_activation);
1857 bus_pending_activation_entry_free (pending_activation_entry);
1861 pending_activation->n_entries += 1;
1862 pending_activation->activation->n_pending_activations += 1;
1865 _dbus_hash_iter_init (activation->pending_activations, &iter);
1866 while (_dbus_hash_iter_next (&iter))
1868 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1870 if (strcmp (p->exec, entry->exec) == 0)
1877 if (!_dbus_hash_table_insert_string (activation->pending_activations,
1878 pending_activation->service_name,
1879 pending_activation))
1881 _dbus_verbose ("Failed to put pending activation in hash table\n");
1883 BUS_SET_OOM (error);
1884 bus_pending_activation_unref (pending_activation);
1889 if (!add_cancel_pending_to_transaction (transaction, pending_activation))
1891 _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
1892 BUS_SET_OOM (error);
1893 _dbus_hash_table_remove_string (activation->pending_activations,
1894 pending_activation->service_name);
1902 if (bus_context_get_systemd_activation (activation->context))
1904 if (strcmp (service_name, "org.freedesktop.systemd1") == 0)
1905 /* systemd itself is missing apparently. That can happen
1906 only during early startup. Let's just wait until systemd
1907 connects to us and do nothing. */
1910 if (entry->systemd_service)
1912 BusTransaction *activation_transaction;
1913 DBusString service_string;
1914 BusService *service;
1915 BusRegistry *registry;
1917 /* OK, we have a systemd service configured for this entry,
1918 hence let's enqueue an activation request message. This
1919 is implemented as a directed signal, not a method call,
1920 for three reasons: 1) we don't expect a response on
1921 success, where we just expect a name appearing on the
1922 bus; 2) at this time the systemd service might not yet
1923 have connected, so we wouldn't know the message serial at
1924 this point to set up a pending call; 3) it is ugly if the
1925 bus suddenly becomes the caller of a remote method. */
1927 message = dbus_message_new_signal (DBUS_PATH_DBUS,
1928 "org.freedesktop.systemd1.Activator",
1929 "ActivationRequest");
1932 _dbus_verbose ("No memory to create activation message\n");
1933 BUS_SET_OOM (error);
1937 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
1938 !dbus_message_set_destination (message, "org.freedesktop.systemd1") ||
1939 !dbus_message_append_args (message,
1940 DBUS_TYPE_STRING, &entry->systemd_service,
1943 _dbus_verbose ("No memory to set args of activation message\n");
1944 dbus_message_unref (message);
1945 BUS_SET_OOM (error);
1949 /* Create our transaction */
1950 activation_transaction = bus_transaction_new (activation->context);
1951 if (activation_transaction == NULL)
1953 _dbus_verbose ("No memory to create activation transaction\n");
1954 dbus_message_unref (message);
1955 BUS_SET_OOM (error);
1959 /* Check whether systemd is already connected */
1960 registry = bus_connection_get_registry (connection);
1961 _dbus_string_init_const (&service_string, "org.freedesktop.systemd1");
1962 service = bus_registry_lookup (registry, &service_string);
1964 if (service != NULL)
1965 /* Wonderful, systemd is connected, let's just send the msg */
1966 retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service),
1969 /* systemd is not around, let's "activate" it. */
1970 retval = bus_activation_activate_service (activation, connection, activation_transaction, TRUE,
1971 message, "org.freedesktop.systemd1", error);
1973 dbus_message_unref (message);
1977 _DBUS_ASSERT_ERROR_IS_SET (error);
1978 _dbus_verbose ("failed to send activation message: %s\n", error->name);
1979 bus_transaction_cancel_and_free (activation_transaction);
1983 bus_transaction_execute_and_free (activation_transaction);
1987 /* OK, we have no configured systemd service, hence let's
1988 proceed with traditional activation. */
1991 /* use command as system and session different */
1992 if (!_dbus_string_init (&command))
1994 BUS_SET_OOM (error);
1998 /* does the bus use a helper? */
1999 servicehelper = bus_context_get_servicehelper (activation->context);
2000 if (servicehelper != NULL)
2002 if (entry->user == NULL)
2004 _dbus_string_free (&command);
2005 dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
2006 "Cannot do system-bus activation with no user\n");
2010 /* join the helper path and the service name */
2011 if (!_dbus_string_append (&command, servicehelper))
2013 _dbus_string_free (&command);
2014 BUS_SET_OOM (error);
2017 if (!_dbus_string_append (&command, " "))
2019 _dbus_string_free (&command);
2020 BUS_SET_OOM (error);
2023 if (!_dbus_string_append (&command, service_name))
2025 _dbus_string_free (&command);
2026 BUS_SET_OOM (error);
2032 /* the bus does not use a helper, so we can append arguments with the exec line */
2033 if (!_dbus_string_append (&command, entry->exec))
2035 _dbus_string_free (&command);
2036 BUS_SET_OOM (error);
2041 /* convert command into arguments */
2042 if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
2044 _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
2045 _DBUS_ASSERT_ERROR_IS_SET (error);
2047 _dbus_hash_table_remove_string (activation->pending_activations,
2048 pending_activation->service_name);
2050 _dbus_string_free (&command);
2053 _dbus_string_free (&command);
2055 if (!add_bus_environment (activation, error))
2057 _DBUS_ASSERT_ERROR_IS_SET (error);
2058 dbus_free_string_array (argv);
2062 envp = bus_activation_get_environment (activation);
2066 BUS_SET_OOM (error);
2067 dbus_free_string_array (argv);
2071 _dbus_verbose ("Spawning %s ...\n", argv[0]);
2072 if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
2077 _dbus_verbose ("Failed to spawn child\n");
2078 _DBUS_ASSERT_ERROR_IS_SET (error);
2079 dbus_free_string_array (argv);
2080 dbus_free_string_array (envp);
2085 dbus_free_string_array (argv);
2088 _dbus_assert (pending_activation->babysitter != NULL);
2090 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
2091 add_babysitter_watch,
2092 remove_babysitter_watch,
2097 BUS_SET_OOM (error);
2098 _dbus_verbose ("Failed to set babysitter watch functions\n");
2106 bus_activation_list_services (BusActivation *activation,
2114 len = _dbus_hash_table_get_n_entries (activation->entries);
2115 retval = dbus_new (char *, len + 1);
2120 _dbus_hash_iter_init (activation->entries, &iter);
2122 while (_dbus_hash_iter_next (&iter))
2124 BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
2126 retval[i] = _dbus_strdup (entry->name);
2127 if (retval[i] == NULL)
2142 for (j = 0; j < i; j++)
2143 dbus_free (retval[i]);
2150 dbus_activation_systemd_failure (BusActivation *activation,
2151 DBusMessage *message)
2154 const char *code, *str, *unit = NULL;
2156 dbus_error_init(&error);
2158 /* This is called whenever the systemd activator sent us a
2159 response. We'll invalidate all pending activations that match the
2162 if (dbus_message_get_args (message, &error,
2163 DBUS_TYPE_STRING, &unit,
2164 DBUS_TYPE_STRING, &code,
2165 DBUS_TYPE_STRING, &str,
2167 dbus_set_error(&error, code, str);
2173 _dbus_hash_iter_init (activation->pending_activations,
2176 while (_dbus_hash_iter_next (&iter))
2178 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
2180 if (p->systemd_service && strcmp (p->systemd_service, unit) == 0)
2181 pending_activation_failed(p, &error);
2185 dbus_error_free(&error);
2190 #ifdef DBUS_BUILD_TESTS
2194 #define SERVICE_NAME_1 "MyService1"
2195 #define SERVICE_NAME_2 "MyService2"
2196 #define SERVICE_NAME_3 "MyService3"
2198 #define SERVICE_FILE_1 "service-1.service"
2199 #define SERVICE_FILE_2 "service-2.service"
2200 #define SERVICE_FILE_3 "service-3.service"
2203 test_create_service_file (DBusString *dir,
2204 const char *filename,
2208 DBusString file_name, full_path;
2210 dbus_bool_t ret_val;
2213 _dbus_string_init_const (&file_name, filename);
2215 if (!_dbus_string_init (&full_path))
2218 if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2219 !_dbus_concat_dir_and_file (&full_path, &file_name))
2225 file = fopen (_dbus_string_get_const_data (&full_path), "w");
2232 fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
2236 _dbus_string_free (&full_path);
2241 test_remove_service_file (DBusString *dir, const char *filename)
2243 DBusString file_name, full_path;
2244 dbus_bool_t ret_val;
2248 _dbus_string_init_const (&file_name, filename);
2250 if (!_dbus_string_init (&full_path))
2253 if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2254 !_dbus_concat_dir_and_file (&full_path, &file_name))
2260 if (!_dbus_delete_file (&full_path, NULL))
2267 _dbus_string_free (&full_path);
2272 test_remove_directory (DBusString *dir)
2275 DBusString filename, full_path;
2276 dbus_bool_t ret_val;
2280 if (!_dbus_string_init (&filename))
2283 if (!_dbus_string_init (&full_path))
2285 _dbus_string_free (&filename);
2289 iter = _dbus_directory_open (dir, NULL);
2296 while (_dbus_directory_get_next_file (iter, &filename, NULL))
2298 if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
2304 _dbus_directory_close (iter);
2306 if (!_dbus_delete_directory (dir, NULL))
2313 _dbus_string_free (&filename);
2314 _dbus_string_free (&full_path);
2320 init_service_reload_test (DBusString *dir)
2324 if (!_dbus_stat (dir, &stat_buf, NULL))
2326 if (!_dbus_create_directory (dir, NULL))
2331 if (!test_remove_directory (dir))
2334 if (!_dbus_create_directory (dir, NULL))
2338 /* Create one initial file */
2339 if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
2346 cleanup_service_reload_test (DBusString *dir)
2348 if (!test_remove_directory (dir))
2356 BusActivation *activation;
2357 const char *service_name;
2358 dbus_bool_t expecting_find;
2362 check_func (void *data)
2365 BusActivationEntry *entry;
2367 dbus_bool_t ret_val;
2372 dbus_error_init (&error);
2374 entry = activation_find_entry (d->activation, d->service_name, &error);
2377 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2383 if (d->expecting_find)
2387 dbus_error_free (&error);
2391 if (!d->expecting_find)
2399 do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
2404 err = !_dbus_test_oom_handling (description, check_func, data);
2406 err = !check_func (data);
2409 _dbus_assert_not_reached ("Test failed");
2415 do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
2417 BusActivation *activation;
2419 DBusList *directories;
2423 _dbus_string_init_const (&address, "");
2425 if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
2428 activation = bus_activation_new (NULL, &address, &directories, NULL);
2432 d.activation = activation;
2434 /* Check for existing service file */
2435 d.expecting_find = TRUE;
2436 d.service_name = SERVICE_NAME_1;
2438 if (!do_test ("Existing service file", oom_test, &d))
2441 /* Check for non-existing service file */
2442 d.expecting_find = FALSE;
2443 d.service_name = SERVICE_NAME_3;
2445 if (!do_test ("Nonexisting service file", oom_test, &d))
2448 /* Check for added service file */
2449 if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
2452 d.expecting_find = TRUE;
2453 d.service_name = SERVICE_NAME_2;
2455 if (!do_test ("Added service file", oom_test, &d))
2458 /* Check for removed service file */
2459 if (!test_remove_service_file (dir, SERVICE_FILE_2))
2462 d.expecting_find = FALSE;
2463 d.service_name = SERVICE_FILE_2;
2465 if (!do_test ("Removed service file", oom_test, &d))
2468 /* Check for updated service file */
2470 _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
2472 if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
2475 d.expecting_find = TRUE;
2476 d.service_name = SERVICE_NAME_3;
2478 if (!do_test ("Updated service file, part 1", oom_test, &d))
2481 d.expecting_find = FALSE;
2482 d.service_name = SERVICE_NAME_1;
2484 if (!do_test ("Updated service file, part 2", oom_test, &d))
2487 bus_activation_unref (activation);
2488 _dbus_list_clear (&directories);
2494 bus_activation_service_reload_test (const DBusString *test_data_dir)
2496 DBusString directory;
2498 if (!_dbus_string_init (&directory))
2501 if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
2504 if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
2505 !_dbus_generate_random_ascii (&directory, 6))
2510 /* Do normal tests */
2511 if (!init_service_reload_test (&directory))
2512 _dbus_assert_not_reached ("could not initiate service reload test");
2514 if (!do_service_reload_test (&directory, FALSE))
2518 if (!init_service_reload_test (&directory))
2519 _dbus_assert_not_reached ("could not initiate service reload test");
2521 if (!do_service_reload_test (&directory, TRUE))
2524 /* Cleanup test directory */
2525 if (!cleanup_service_reload_test (&directory))
2528 _dbus_string_free (&directory);
2533 #endif /* DBUS_BUILD_TESTS */