Compare commits
18 Commits
222a6aace7
...
a50414fce5
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | a50414fce5 | |
Zbigniew Jędrzejewski-Szmek | 8c5cd27dd1 | |
Zbigniew Jędrzejewski-Szmek | b6bcde2623 | |
Lennart Poettering | eea45a3399 | |
Lennart Poettering | f6160131e7 | |
Zbigniew Jędrzejewski-Szmek | 6af0a04428 | |
Zbigniew Jędrzejewski-Szmek | 4e96d758f8 | |
Zbigniew Jędrzejewski-Szmek | 48f60ea9ad | |
Zbigniew Jędrzejewski-Szmek | d00386fc0b | |
Lennart Poettering | fc67a943d9 | |
Lennart Poettering | a5b0784795 | |
Lennart Poettering | 5085ef0d71 | |
Lennart Poettering | 17bda1f19d | |
Lennart Poettering | a54654ba70 | |
Lennart Poettering | 42837b8134 | |
Lennart Poettering | 3425c45e1e | |
Lennart Poettering | 13811aa5f6 | |
Lennart Poettering | 519b2e5212 |
|
@ -2,6 +2,8 @@
|
||||||
title: Hacking on systemd
|
title: Hacking on systemd
|
||||||
category: Contributing
|
category: Contributing
|
||||||
layout: default
|
layout: default
|
||||||
|
redirect_from:
|
||||||
|
- HACKING/
|
||||||
---
|
---
|
||||||
|
|
||||||
# Hacking on systemd
|
# Hacking on systemd
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
title: Users, Groups, UIDs and GIDs on `systemd` Systems
|
title: Users, Groups, UIDs and GIDs on systemd Systems
|
||||||
category: Concepts
|
category: Concepts
|
||||||
layout: default
|
layout: default
|
||||||
---
|
---
|
||||||
|
|
||||||
# Users, Groups, UIDs and GIDs on `systemd` Systems
|
# Users, Groups, UIDs and GIDs on systemd Systems
|
||||||
|
|
||||||
Here's a summary of the requirements `systemd` (and Linux) make on UID/GID
|
Here's a summary of the requirements `systemd` (and Linux) make on UID/GID
|
||||||
assignments and their ranges.
|
assignments and their ranges.
|
||||||
|
|
|
@ -8,8 +8,6 @@ systemd provides aggressive parallelization capabilities, uses socket and D-Bus
|
||||||
|
|
||||||
Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution.
|
Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution.
|
||||||
|
|
||||||
See the introductory blog story and three status updates for a longer introduction. Also see the [Wikipedia article](https://en.wikipedia.org/wiki/systemd).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
{% assign by_category = site.pages | group_by:"category" %}
|
{% assign by_category = site.pages | group_by:"category" %}
|
||||||
|
@ -24,3 +22,74 @@ See the introductory blog story and three status updates for a longer introducti
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* [Introductory blog story](http://0pointer.de/blog/projects/systemd.html)
|
||||||
|
* [Three](http://0pointer.de/blog/projects/systemd-update.html) [status](http://0pointer.de/blog/projects/systemd-update-2.html) [updates](http://0pointer.de/blog/projects/systemd-update-3.html)
|
||||||
|
* The [Wikipedia article](https://en.wikipedia.org/wiki/systemd)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<pre style="color:white; background-color:black; font-size:smaller; width:45%; padding:6pt 8pt">
|
||||||
|
Welcome to <span style="color:blue">Fedora 20 (Heisenbug)</span>!
|
||||||
|
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Remote File Systems.
|
||||||
|
[ <span style="color:green">OK</span> ] Listening on Delayed Shutdown Socket.
|
||||||
|
[ <span style="color:green">OK</span> ] Listening on /dev/initctl Compatibility Named Pipe.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Paths.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Encrypted Volumes.
|
||||||
|
[ <span style="color:green">OK</span> ] Listening on Journal Socket.
|
||||||
|
Mounting Huge Pages File System...
|
||||||
|
Mounting POSIX Message Queue File System...
|
||||||
|
Mounting Debug File System...
|
||||||
|
Starting Journal Service...
|
||||||
|
[ <span style="color:green">OK</span> ] Started Journal Service.
|
||||||
|
Mounting Configuration File System...
|
||||||
|
Mounting FUSE Control File System...
|
||||||
|
[ <span style="color:green">OK</span> ] Created slice Root Slice.
|
||||||
|
[ <span style="color:green">OK</span> ] Created slice User and Session Slice.
|
||||||
|
[ <span style="color:green">OK</span> ] Created slice System Slice.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Slices.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Swap.
|
||||||
|
Mounting Temporary Directory...
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Local File Systems (Pre).
|
||||||
|
Starting Load Random Seed...
|
||||||
|
Starting Load/Save Random Seed...
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted Huge Pages File System.
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted POSIX Message Queue File System.
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted Debug File System.
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted Configuration File System.
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted FUSE Control File System.
|
||||||
|
[ <span style="color:green">OK</span> ] Mounted Temporary Directory.
|
||||||
|
[ <span style="color:green">OK</span> ] Started Load Random Seed.
|
||||||
|
[ <span style="color:green">OK</span> ] Started Load/Save Random Seed.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Local File Systems.
|
||||||
|
Starting Recreate Volatile Files and Directories...
|
||||||
|
Starting Trigger Flushing of Journal to Persistent Storage...
|
||||||
|
[ <span style="color:green">OK</span> ] Started Recreate Volatile Files and Directories.
|
||||||
|
Starting Update UTMP about System Reboot/Shutdown...
|
||||||
|
[ <span style="color:green">OK</span> ] Started Trigger Flushing of Journal to Persistent Storage.
|
||||||
|
[ <span style="color:green">OK</span> ] Started Update UTMP about System Reboot/Shutdown.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target System Initialization.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Timers.
|
||||||
|
[ <span style="color:green">OK</span> ] Listening on D-Bus System Message Bus Socket.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Sockets.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Basic System.
|
||||||
|
Starting Permit User Sessions...
|
||||||
|
Starting D-Bus System Message Bus...
|
||||||
|
[ <span style="color:green">OK</span> ] Started D-Bus System Message Bus.
|
||||||
|
Starting Login Service...
|
||||||
|
Starting Cleanup of Temporary Directories...
|
||||||
|
[ <span style="color:green">OK</span> ] Started Permit User Sessions.
|
||||||
|
[ <span style="color:green">OK</span> ] Started Cleanup of Temporary Directories.
|
||||||
|
Starting Console Getty...
|
||||||
|
[ <span style="color:green">OK</span> ] Started Console Getty.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Login Prompts.
|
||||||
|
[ <span style="color:green">OK</span> ] Started Login Service.
|
||||||
|
[ <span style="color:green">OK</span> ] Reached target Multi-User System.
|
||||||
|
|
||||||
|
Fedora release 20 (Heisenbug)
|
||||||
|
Kernel 3.9.2-200.fc18.x86_64 on an x86_64 (console)
|
||||||
|
|
||||||
|
fedora login:
|
||||||
|
</pre>
|
||||||
|
|
|
@ -46,14 +46,14 @@
|
||||||
Control Group Interfaces</ulink> for an introduction on how to make
|
Control Group Interfaces</ulink> for an introduction on how to make
|
||||||
use of scope units from programs.</para>
|
use of scope units from programs.</para>
|
||||||
|
|
||||||
<para>Note that unlike service units scope units have no "main" process, all processes in the scope are
|
<para>Note that, unlike service units, scope units have no "main" process: all processes in the scope are
|
||||||
equivalent. The lifecycle of the scope unit is thus not bound to the lifetime of one specific process but
|
equivalent. The lifecycle of the scope unit is thus not bound to the lifetime of one specific process,
|
||||||
to the existance of any processes in the scope. This also means that the exit status of these processes
|
but to the existence of at least one process in the scope. This also means that the exit statuses of
|
||||||
do not cause the scope unit to enter a failure state. Scope units may still enter a failure state, for
|
these processes are not relevant for the scope unit failure state. Scope units may still enter a failure
|
||||||
example due to resource exhaustion or stop timeouts being reached, but not due to programs inside of them
|
state, for example due to resource exhaustion or stop timeouts being reached, but not due to programs
|
||||||
terminating uncleanly. Since processes managed as scope units generally remain children of the original
|
inside of them terminating uncleanly. Since processes managed as scope units generally remain children of
|
||||||
process that forked them off it's also the job of that process to collect their exit statuses and act on
|
the original process that forked them off, it is also the job of that process to collect their exit
|
||||||
them as needed.</para>
|
statuses and act on them as needed.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|
|
@ -2993,7 +2993,7 @@ install_data('LICENSE.GPL2',
|
||||||
'docs/CODING_STYLE.md',
|
'docs/CODING_STYLE.md',
|
||||||
'docs/DISTRO_PORTING.md',
|
'docs/DISTRO_PORTING.md',
|
||||||
'docs/ENVIRONMENT.md',
|
'docs/ENVIRONMENT.md',
|
||||||
'docs/HACKING.md',
|
'docs/Hacking.md',
|
||||||
'docs/TRANSIENT-SETTINGS.md',
|
'docs/TRANSIENT-SETTINGS.md',
|
||||||
'docs/TRANSLATORS.md',
|
'docs/TRANSLATORS.md',
|
||||||
'docs/UIDS-GIDS.md',
|
'docs/UIDS-GIDS.md',
|
||||||
|
|
121
src/core/dbus.c
121
src/core/dbus.c
|
@ -719,114 +719,6 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) {
|
|
||||||
_cleanup_strv_free_ char **names = NULL;
|
|
||||||
Manager *m = userdata;
|
|
||||||
const char *name;
|
|
||||||
Iterator i;
|
|
||||||
Unit *u;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(es);
|
|
||||||
assert(m);
|
|
||||||
assert(m->sync_bus_names_event_source == es);
|
|
||||||
|
|
||||||
/* First things first, destroy the defer event so that we aren't triggered again */
|
|
||||||
m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source);
|
|
||||||
|
|
||||||
/* Let's see if there's anything to do still? */
|
|
||||||
if (!m->api_bus)
|
|
||||||
return 0;
|
|
||||||
if (hashmap_isempty(m->watch_bus))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* OK, let's sync up the names. Let's see which names are currently on the bus. */
|
|
||||||
r = sd_bus_list_names(m->api_bus, &names, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to get initial list of names: %m");
|
|
||||||
|
|
||||||
/* We have to synchronize the current bus names with the
|
|
||||||
* list of active services. To do this, walk the list of
|
|
||||||
* all units with bus names. */
|
|
||||||
HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
|
|
||||||
Service *s = SERVICE(u);
|
|
||||||
|
|
||||||
assert(s);
|
|
||||||
|
|
||||||
if (!streq_ptr(s->bus_name, name)) {
|
|
||||||
log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if a service's bus name is in the list of currently
|
|
||||||
* active names */
|
|
||||||
if (strv_contains(names, name)) {
|
|
||||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
||||||
const char *unique;
|
|
||||||
|
|
||||||
/* If it is, determine its current owner */
|
|
||||||
r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
|
|
||||||
if (r < 0) {
|
|
||||||
log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_bus_creds_get_unique_name(creds, &unique);
|
|
||||||
if (r < 0) {
|
|
||||||
log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now, let's compare that to the previous bus owner, and
|
|
||||||
* if it's still the same, all is fine, so just don't
|
|
||||||
* bother the service. Otherwise, the name has apparently
|
|
||||||
* changed, so synthesize a name owner changed signal. */
|
|
||||||
|
|
||||||
if (!streq_ptr(unique, s->bus_name_owner))
|
|
||||||
UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, unique);
|
|
||||||
} else {
|
|
||||||
/* So, the name we're watching is not on the bus.
|
|
||||||
* This either means it simply hasn't appeared yet,
|
|
||||||
* or it was lost during the daemon reload.
|
|
||||||
* Check if the service has a stored name owner,
|
|
||||||
* and synthesize a name loss signal in this case. */
|
|
||||||
|
|
||||||
if (s->bus_name_owner)
|
|
||||||
UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int manager_enqueue_sync_bus_names(Manager *m) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(m);
|
|
||||||
|
|
||||||
/* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't
|
|
||||||
* want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event
|
|
||||||
* dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */
|
|
||||||
|
|
||||||
if (m->sync_bus_names_event_source)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to create bus name synchronization event: %m");
|
|
||||||
|
|
||||||
r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to set event priority: %m");
|
|
||||||
|
|
||||||
r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to set even to oneshot: %m");
|
|
||||||
|
|
||||||
(void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bus_setup_api(Manager *m, sd_bus *bus) {
|
static int bus_setup_api(Manager *m, sd_bus *bus) {
|
||||||
Iterator i;
|
Iterator i;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -910,10 +802,6 @@ int bus_init_api(Manager *m) {
|
||||||
|
|
||||||
m->api_bus = TAKE_PTR(bus);
|
m->api_bus = TAKE_PTR(bus);
|
||||||
|
|
||||||
r = manager_enqueue_sync_bus_names(m);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,13 +939,10 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
|
||||||
|
|
||||||
/* Make sure all bus slots watching names are released. */
|
/* Make sure all bus slots watching names are released. */
|
||||||
HASHMAP_FOREACH(u, m->watch_bus, i) {
|
HASHMAP_FOREACH(u, m->watch_bus, i) {
|
||||||
if (!u->match_bus_slot)
|
if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus)
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||||
|
if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus)
|
||||||
|
u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get rid of tracked clients on this bus */
|
/* Get rid of tracked clients on this bus */
|
||||||
|
|
|
@ -21,8 +21,6 @@ int bus_fdset_add_all(Manager *m, FDSet *fds);
|
||||||
void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix);
|
void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix);
|
||||||
int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l);
|
int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l);
|
||||||
|
|
||||||
int manager_enqueue_sync_bus_names(Manager *m);
|
|
||||||
|
|
||||||
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
|
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
|
||||||
|
|
||||||
int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
||||||
|
|
|
@ -1373,7 +1373,6 @@ Manager* manager_free(Manager *m) {
|
||||||
sd_event_source_unref(m->jobs_in_progress_event_source);
|
sd_event_source_unref(m->jobs_in_progress_event_source);
|
||||||
sd_event_source_unref(m->run_queue_event_source);
|
sd_event_source_unref(m->run_queue_event_source);
|
||||||
sd_event_source_unref(m->user_lookup_event_source);
|
sd_event_source_unref(m->user_lookup_event_source);
|
||||||
sd_event_source_unref(m->sync_bus_names_event_source);
|
|
||||||
|
|
||||||
safe_close(m->signal_fd);
|
safe_close(m->signal_fd);
|
||||||
safe_close(m->notify_fd);
|
safe_close(m->notify_fd);
|
||||||
|
@ -1610,9 +1609,6 @@ static void manager_ready(Manager *m) {
|
||||||
manager_recheck_journal(m);
|
manager_recheck_journal(m);
|
||||||
manager_recheck_dbus(m);
|
manager_recheck_dbus(m);
|
||||||
|
|
||||||
/* Sync current state of bus names with our set of listening units */
|
|
||||||
(void) manager_enqueue_sync_bus_names(m);
|
|
||||||
|
|
||||||
/* Let's finally catch up with any changes that took place while we were reloading/reexecing */
|
/* Let's finally catch up with any changes that took place while we were reloading/reexecing */
|
||||||
manager_catchup(m);
|
manager_catchup(m);
|
||||||
|
|
||||||
|
|
|
@ -219,8 +219,6 @@ struct Manager {
|
||||||
int user_lookup_fds[2];
|
int user_lookup_fds[2];
|
||||||
sd_event_source *user_lookup_event_source;
|
sd_event_source *user_lookup_event_source;
|
||||||
|
|
||||||
sd_event_source *sync_bus_names_event_source;
|
|
||||||
|
|
||||||
UnitFileScope unit_file_scope;
|
UnitFileScope unit_file_scope;
|
||||||
LookupPaths lookup_paths;
|
LookupPaths lookup_paths;
|
||||||
Hashmap *unit_id_map;
|
Hashmap *unit_id_map;
|
||||||
|
|
|
@ -4062,24 +4062,17 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void service_bus_name_owner_change(
|
static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
|
||||||
Unit *u,
|
|
||||||
const char *old_owner,
|
|
||||||
const char *new_owner) {
|
|
||||||
|
|
||||||
Service *s = SERVICE(u);
|
Service *s = SERVICE(u);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
assert(old_owner || new_owner);
|
if (new_owner)
|
||||||
|
log_unit_debug(u, "D-Bus name %s now owned by %s", s->bus_name, new_owner);
|
||||||
if (old_owner && new_owner)
|
|
||||||
log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", s->bus_name, old_owner, new_owner);
|
|
||||||
else if (old_owner)
|
|
||||||
log_unit_debug(u, "D-Bus name %s no longer registered by %s", s->bus_name, old_owner);
|
|
||||||
else
|
else
|
||||||
log_unit_debug(u, "D-Bus name %s now registered by %s", s->bus_name, new_owner);
|
log_unit_debug(u, "D-Bus name %s now not owned by anyone.", s->bus_name);
|
||||||
|
|
||||||
s->bus_name_good = !!new_owner;
|
s->bus_name_good = !!new_owner;
|
||||||
|
|
||||||
|
|
|
@ -3201,24 +3201,21 @@ int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
const char *name, *old_owner, *new_owner;
|
const char *new_owner;
|
||||||
Unit *u = userdata;
|
Unit *u = userdata;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
|
r = sd_bus_message_read(message, "sss", NULL, NULL, &new_owner);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
bus_log_parse_error(r);
|
bus_log_parse_error(r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_owner = empty_to_null(old_owner);
|
|
||||||
new_owner = empty_to_null(new_owner);
|
|
||||||
|
|
||||||
if (UNIT_VTABLE(u)->bus_name_owner_change)
|
if (UNIT_VTABLE(u)->bus_name_owner_change)
|
||||||
UNIT_VTABLE(u)->bus_name_owner_change(u, old_owner, new_owner);
|
UNIT_VTABLE(u)->bus_name_owner_change(u, empty_to_null(new_owner));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3234,42 +3231,35 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu
|
||||||
|
|
||||||
u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
|
u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
|
||||||
|
|
||||||
if (sd_bus_error_is_set(error)) {
|
|
||||||
log_error("Failed to get name owner from bus: %s", error->message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = sd_bus_message_get_error(message);
|
e = sd_bus_message_get_error(message);
|
||||||
if (sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
log_error("Unexpected error response from GetNameOwner: %s", e->message);
|
if (!sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner"))
|
||||||
return 0;
|
log_unit_error(u, "Unexpected error response from GetNameOwner(): %s", e->message);
|
||||||
}
|
|
||||||
|
|
||||||
|
new_owner = NULL;
|
||||||
|
} else {
|
||||||
r = sd_bus_message_read(message, "s", &new_owner);
|
r = sd_bus_message_read(message, "s", &new_owner);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
bus_log_parse_error(r);
|
return bus_log_parse_error(r);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_owner = empty_to_null(new_owner);
|
assert(!isempty(new_owner));
|
||||||
|
}
|
||||||
|
|
||||||
if (UNIT_VTABLE(u)->bus_name_owner_change)
|
if (UNIT_VTABLE(u)->bus_name_owner_change)
|
||||||
UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner);
|
UNIT_VTABLE(u)->bus_name_owner_change(u, new_owner);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||||
const char *match;
|
const char *match;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
assert(bus);
|
assert(bus);
|
||||||
assert(name);
|
assert(name);
|
||||||
|
|
||||||
if (u->match_bus_slot)
|
if (u->match_bus_slot || u->get_name_owner_slot)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
match = strjoina("type='signal',"
|
match = strjoina("type='signal',"
|
||||||
|
@ -3279,11 +3269,12 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||||
"member='NameOwnerChanged',"
|
"member='NameOwnerChanged',"
|
||||||
"arg0='", name, "'");
|
"arg0='", name, "'");
|
||||||
|
|
||||||
int r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
|
r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return sd_bus_call_method_async(bus,
|
r = sd_bus_call_method_async(
|
||||||
|
bus,
|
||||||
&u->get_name_owner_slot,
|
&u->get_name_owner_slot,
|
||||||
"org.freedesktop.DBus",
|
"org.freedesktop.DBus",
|
||||||
"/org/freedesktop/DBus",
|
"/org/freedesktop/DBus",
|
||||||
|
@ -3292,6 +3283,13 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||||
get_name_owner_handler,
|
get_name_owner_handler,
|
||||||
u,
|
u,
|
||||||
"s", name);
|
"s", name);
|
||||||
|
if (r < 0) {
|
||||||
|
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_unit_debug(u, "Watching D-Bus name '%s'.", name);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unit_watch_bus_name(Unit *u, const char *name) {
|
int unit_watch_bus_name(Unit *u, const char *name) {
|
||||||
|
@ -3314,6 +3312,7 @@ int unit_watch_bus_name(Unit *u, const char *name) {
|
||||||
r = hashmap_put(u->manager->watch_bus, name, u);
|
r = hashmap_put(u->manager->watch_bus, name, u);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||||
|
u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
|
||||||
return log_warning_errno(r, "Failed to put bus name to hashmap: %m");
|
return log_warning_errno(r, "Failed to put bus name to hashmap: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,7 @@ typedef struct UnitVTable {
|
||||||
void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds);
|
void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds);
|
||||||
|
|
||||||
/* Called whenever a name this Unit registered for comes or goes away. */
|
/* Called whenever a name this Unit registered for comes or goes away. */
|
||||||
void (*bus_name_owner_change)(Unit *u, const char *old_owner, const char *new_owner);
|
void (*bus_name_owner_change)(Unit *u, const char *new_owner);
|
||||||
|
|
||||||
/* Called for each property that is being set */
|
/* Called for each property that is being set */
|
||||||
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||||
|
|
Loading…
Reference in New Issue