logind: rework Seat/Session/User object allocation and freeing a bit

Let's update things a bit to follow current practices:

- User structure initialization rather than zero-initialized allocation

- Always propagate proper errors from allocation functions

- Use _cleanup_ for freeing objects when allocation fails half-way

- Make destructors return NULL
This commit is contained in:
Lennart Poettering 2018-08-03 18:53:09 +02:00
parent fd8879498d
commit 8c29a45709
6 changed files with 83 additions and 60 deletions

View File

@ -90,15 +90,16 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
int manager_add_seat(Manager *m, const char *id, Seat **_seat) { int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
Seat *s; Seat *s;
int r;
assert(m); assert(m);
assert(id); assert(id);
s = hashmap_get(m->seats, id); s = hashmap_get(m->seats, id);
if (!s) { if (!s) {
s = seat_new(m, id); r = seat_new(&s, m, id);
if (!s) if (r < 0)
return -ENOMEM; return r;
} }
if (_seat) if (_seat)
@ -109,15 +110,16 @@ int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
int manager_add_session(Manager *m, const char *id, Session **_session) { int manager_add_session(Manager *m, const char *id, Session **_session) {
Session *s; Session *s;
int r;
assert(m); assert(m);
assert(id); assert(id);
s = hashmap_get(m->sessions, id); s = hashmap_get(m->sessions, id);
if (!s) { if (!s) {
s = session_new(m, id); r = session_new(&s, m, id);
if (!s) if (r < 0)
return -ENOMEM; return r;
} }
if (_session) if (_session)

View File

@ -21,33 +21,42 @@
#include "terminal-util.h" #include "terminal-util.h"
#include "util.h" #include "util.h"
Seat *seat_new(Manager *m, const char *id) { int seat_new(Seat** ret, Manager *m, const char *id) {
Seat *s; _cleanup_(seat_freep) Seat *s = NULL;
int r;
assert(ret);
assert(m); assert(m);
assert(id); assert(id);
s = new0(Seat, 1); if (!seat_name_is_valid(id))
return -EINVAL;
s = new(Seat, 1);
if (!s) if (!s)
return NULL; return -ENOMEM;
*s = (Seat) {
.manager = m,
};
s->state_file = strappend("/run/systemd/seats/", id); s->state_file = strappend("/run/systemd/seats/", id);
if (!s->state_file) if (!s->state_file)
return mfree(s); return -ENOMEM;
s->id = basename(s->state_file); s->id = basename(s->state_file);
s->manager = m;
if (hashmap_put(m->seats, s->id, s) < 0) { r = hashmap_put(m->seats, s->id, s);
free(s->state_file); if (r < 0)
return mfree(s); return r;
}
return s; *ret = TAKE_PTR(s);
return 0;
} }
void seat_free(Seat *s) { Seat* seat_free(Seat *s) {
assert(s); if (!s)
return NULL;
if (s->in_gc_queue) if (s->in_gc_queue)
LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s); LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s);
@ -64,7 +73,8 @@ void seat_free(Seat *s) {
free(s->positions); free(s->positions);
free(s->state_file); free(s->state_file);
free(s);
return mfree(s);
} }
int seat_save(Seat *s) { int seat_save(Seat *s) {

View File

@ -27,8 +27,10 @@ struct Seat {
LIST_FIELDS(Seat, gc_queue); LIST_FIELDS(Seat, gc_queue);
}; };
Seat *seat_new(Manager *m, const char *id); int seat_new(Seat **ret, Manager *m, const char *id);
void seat_free(Seat *s); Seat* seat_free(Seat *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free);
int seat_save(Seat *s); int seat_save(Seat *s);
int seat_load(Seat *s); int seat_load(Seat *s);

View File

@ -24,57 +24,61 @@
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h"
#include "string-table.h" #include "string-table.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "user-util.h" #include "user-util.h"
#include "util.h" #include "util.h"
#include "process-util.h"
#define RELEASE_USEC (20*USEC_PER_SEC) #define RELEASE_USEC (20*USEC_PER_SEC)
static void session_remove_fifo(Session *s); static void session_remove_fifo(Session *s);
Session* session_new(Manager *m, const char *id) { int session_new(Session **ret, Manager *m, const char *id) {
Session *s; _cleanup_(session_freep) Session *s = NULL;
int r;
assert(ret);
assert(m); assert(m);
assert(id); assert(id);
assert(session_id_valid(id));
s = new0(Session, 1); if (!session_id_valid(id))
return -EINVAL;
s = new(Session, 1);
if (!s) if (!s)
return NULL; return -ENOMEM;
*s = (Session) {
.manager = m,
.fifo_fd = -1,
.vtfd = -1,
.audit_id = AUDIT_SESSION_INVALID,
};
s->state_file = strappend("/run/systemd/sessions/", id); s->state_file = strappend("/run/systemd/sessions/", id);
if (!s->state_file) if (!s->state_file)
return mfree(s); return -ENOMEM;
s->devices = hashmap_new(&devt_hash_ops);
if (!s->devices) {
free(s->state_file);
return mfree(s);
}
s->id = basename(s->state_file); s->id = basename(s->state_file);
if (hashmap_put(m->sessions, s->id, s) < 0) { s->devices = hashmap_new(&devt_hash_ops);
hashmap_free(s->devices); if (!s->devices)
free(s->state_file); return -ENOMEM;
return mfree(s);
}
s->manager = m; r = hashmap_put(m->sessions, s->id, s);
s->fifo_fd = -1; if (r < 0)
s->vtfd = -1; return r;
s->audit_id = AUDIT_SESSION_INVALID;
return s; *ret = TAKE_PTR(s);
return 0;
} }
void session_free(Session *s) { Session* session_free(Session *s) {
SessionDevice *sd; SessionDevice *sd;
assert(s); if (!s)
return NULL;
if (s->in_gc_queue) if (s->in_gc_queue)
LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s); LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
@ -126,7 +130,8 @@ void session_free(Session *s) {
hashmap_remove(s->manager->sessions, s->id); hashmap_remove(s->manager->sessions, s->id);
free(s->state_file); free(s->state_file);
free(s);
return mfree(s);
} }
void session_set_user(Session *s, User *u) { void session_set_user(Session *s, User *u) {

View File

@ -109,8 +109,11 @@ struct Session {
LIST_FIELDS(Session, gc_queue); LIST_FIELDS(Session, gc_queue);
}; };
Session *session_new(Manager *m, const char *id); int session_new(Session **ret, Manager *m, const char *id);
void session_free(Session *s); Session* session_free(Session *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free);
void session_set_user(Session *s, User *u); void session_set_user(Session *s, User *u);
bool session_may_gc(Session *s, bool drop_not_started); bool session_may_gc(Session *s, bool drop_not_started);
void session_add_to_gc_queue(Session *s); void session_add_to_gc_queue(Session *s);

View File

@ -30,23 +30,24 @@
#include "user-util.h" #include "user-util.h"
#include "util.h" #include "util.h"
int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) { int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
_cleanup_(user_freep) User *u = NULL; _cleanup_(user_freep) User *u = NULL;
char lu[DECIMAL_STR_MAX(uid_t) + 1]; char lu[DECIMAL_STR_MAX(uid_t) + 1];
int r; int r;
assert(out); assert(ret);
assert(m); assert(m);
assert(name); assert(name);
u = new0(User, 1); u = new(User, 1);
if (!u) if (!u)
return -ENOMEM; return -ENOMEM;
u->manager = m; *u = (User) {
u->uid = uid; .manager = m,
u->gid = gid; .uid = uid,
xsprintf(lu, UID_FMT, uid); .gid = gid,
};
u->name = strdup(name); u->name = strdup(name);
if (!u->name) if (!u->name)
@ -58,6 +59,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0) if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
return -ENOMEM; return -ENOMEM;
xsprintf(lu, UID_FMT, uid);
r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice); r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
if (r < 0) if (r < 0)
return r; return r;
@ -78,8 +80,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0) if (r < 0)
return r; return r;
*out = TAKE_PTR(u); *ret = TAKE_PTR(u);
return 0; return 0;
} }
@ -272,7 +273,7 @@ int user_save(User *u) {
if (!u->started) if (!u->started)
return 0; return 0;
return user_save_internal (u); return user_save_internal(u);
} }
int user_load(User *u) { int user_load(User *u) {