return 0;
}
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
+int manager_get_session_by_pidref(Manager *m, const PidRef *pid, Session **ret) {
_cleanup_free_ char *unit = NULL;
Session *s;
int r;
assert(m);
- if (!pid_is_valid(pid))
+ if (!pidref_is_set(pid))
return -EINVAL;
- s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(pid));
- if (!s) {
- r = cg_pid_get_unit(pid, &unit);
- if (r >= 0)
- s = hashmap_get(m->session_units, unit);
+ s = hashmap_get(m->sessions_by_leader, pid);
+ if (s) {
+ r = pidref_verify(pid);
+ if (r < 0)
+ return r;
+ } else {
+ r = cg_pidref_get_unit(pid, &unit);
+ if (r < 0)
+ return r;
+
+ s = hashmap_get(m->session_units, unit);
}
if (ret)
if (isempty(t))
continue;
- s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid));
- if (!s)
+ if (manager_get_session_by_pidref(m, &PIDREF_MAKE_FROM_PID(u->ut_pid), &s) <= 0)
continue;
if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
* as apps may instead belong to a user service unit. This includes terminal
* emulators and hence command-line apps. */
static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = ASSERT_PTR(userdata);
_cleanup_free_ char *p = NULL;
Session *session = NULL;
- Manager *m = ASSERT_PTR(userdata);
pid_t pid;
int r;
if (r < 0)
return r;
} else {
- r = manager_get_session_by_pid(m, pid, &session);
+ r = manager_get_session_by_pidref(m, &PIDREF_MAKE_FROM_PID(pid), &session);
if (r < 0)
return r;
return what;
}
-static int pid_is_active(Manager *m, pid_t pid) {
+static int pidref_is_active_session(Manager *m, const PidRef *pid) {
Session *s;
int r;
- /* Get client session. This is not what you are looking for these days.
+ assert(m);
+ assert(pid);
+
+ /* Get client session. This is not what you are looking for these days.
* FIXME #6852 */
- r = manager_get_session_by_pid(m, pid, &s);
+ r = manager_get_session_by_pidref(m, pid, &s);
if (r < 0)
return r;
- /* If there's no session assigned to it, then it's globally
- * active on all ttys */
+ /* If there's no session assigned to it, then it's globally active on all ttys */
if (r == 0)
return 1;
if (i->mode != mm)
continue;
- if (ignore_inactive && pid_is_active(m, i->pid.pid) <= 0)
+ if (ignore_inactive && pidref_is_active_session(m, &i->pid) <= 0)
continue;
if (ignore_uid && i->uid == uid)
return 0;
}
+static void session_reset_leader(Session *s) {
+ assert(s);
+
+ if (!pidref_is_set(&s->leader))
+ return;
+
+ assert_se(hashmap_remove_value(s->manager->sessions_by_leader, &s->leader, s));
+
+ return pidref_done(&s->leader);
+}
+
Session* session_free(Session *s) {
SessionDevice *sd;
free(s->scope);
}
- if (pidref_is_set(&s->leader)) {
- (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader.pid), s);
- pidref_done(&s->leader);
- }
-
free(s->scope_job);
+ session_reset_leader(s);
+
sd_bus_message_unref(s->create_message);
free(s->tty);
if (pidref_equal(&s->leader, &pidref))
return 0;
- r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pidref.pid), s);
+ session_reset_leader(s);
+
+ s->leader = TAKE_PIDREF(pidref);
+
+ r = hashmap_ensure_put(&s->manager->sessions_by_leader, &pidref_hash_ops, &s->leader, s);
if (r < 0)
return r;
+ assert(r > 0);
- if (pidref_is_set(&s->leader)) {
- (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader.pid), s);
- pidref_done(&s->leader);
- }
-
- s->leader = TAKE_PIDREF(pidref);
(void) audit_session_from_pid(s->leader.pid, &s->audit_id);
return 1;
seat_save(s->seat);
}
- pidref_done(&s->leader);
+ session_reset_leader(s);
user_save(s->user);
user_send_changed(s->user, "Display", NULL);
m->devices = hashmap_new(&device_hash_ops);
m->seats = hashmap_new(&seat_hash_ops);
m->sessions = hashmap_new(&session_hash_ops);
- m->sessions_by_leader = hashmap_new(NULL);
m->users = hashmap_new(&user_hash_ops);
m->inhibitors = hashmap_new(&inhibitor_hash_ops);
m->buttons = hashmap_new(&button_hash_ops);
m->user_units = hashmap_new(&string_hash_ops);
m->session_units = hashmap_new(&string_hash_ops);
- if (!m->devices || !m->seats || !m->sessions || !m->sessions_by_leader || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
+ if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
return -ENOMEM;
r = sd_event_default(&m->event);
hashmap_free(m->devices);
hashmap_free(m->seats);
hashmap_free(m->sessions);
+
+ /* All records should have been removed by session_free */
+ assert(hashmap_isempty(m->sessions_by_leader));
hashmap_free(m->sessions_by_leader);
+
hashmap_free(m->users);
hashmap_free(m->inhibitors);
hashmap_free(m->buttons);
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
int manager_get_user_by_pid(Manager *m, pid_t pid, User **user);
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
+int manager_get_session_by_pidref(Manager *m, const PidRef *pid, Session **ret);
bool manager_is_lid_closed(Manager *m);
bool manager_is_docked_or_external_displays(Manager *m);