X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-rtnl%2Fsd-rtnl.c;h=2ab9d90aa790d4f76360d6adc45111d2b6a6fe1b;hb=0a827d105de9d3d502f22e77fb3ff83da479c2e7;hp=1c2c8902f95140efc2c169cdf3f1cb426b78edd2;hpb=1f0db3ed88015a0510b8bf4723af2121ee55d9a8;p=elogind.git diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 1c2c8902f..2ab9d90aa 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -31,7 +31,7 @@ #include "rtnl-util.h" static int sd_rtnl_new(sd_rtnl **ret) { - sd_rtnl *rtnl; + _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; assert_return(ret, -EINVAL); @@ -52,12 +52,12 @@ static int sd_rtnl_new(sd_rtnl **ret) { /* We guarantee that wqueue always has space for at least * one entry */ rtnl->wqueue = new(sd_rtnl_message*, 1); - if (!rtnl->wqueue) { - free(rtnl); + if (!rtnl->wqueue) return -ENOMEM; - } *ret = rtnl; + rtnl = NULL; + return 0; } @@ -104,6 +104,9 @@ int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) { } sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) { + assert_return(rtnl, NULL); + assert_return(!rtnl_pid_changed(rtnl), NULL); + if (rtnl) assert_se(REFCNT_INC(rtnl->n_ref) >= 2); @@ -111,8 +114,12 @@ sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) { } sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) { + if (!rtnl) + return NULL; + + assert_return(!rtnl_pid_changed(rtnl), NULL); - if (rtnl && REFCNT_DEC(rtnl->n_ref) <= 0) { + if (REFCNT_DEC(rtnl->n_ref) <= 0) { struct match_callback *f; unsigned i; @@ -127,20 +134,36 @@ sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) { hashmap_free_free(rtnl->reply_callbacks); prioq_free(rtnl->reply_callbacks_prioq); + sd_event_source_unref(rtnl->io_event_source); + sd_event_source_unref(rtnl->time_event_source); + sd_event_source_unref(rtnl->exit_event_source); + sd_event_unref(rtnl->event); + while ((f = rtnl->match_callbacks)) { LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f); free(f); } - if (rtnl->fd >= 0) - close_nointr_nofail(rtnl->fd); - + safe_close(rtnl->fd); free(rtnl); } return NULL; } +static void rtnl_seal_message(sd_rtnl *rtnl, sd_rtnl_message *m) { + assert(rtnl); + assert(!rtnl_pid_changed(rtnl)); + assert(m); + assert(m->hdr); + + m->hdr->nlmsg_seq = rtnl->serial++; + + rtnl_message_seal(m); + + return; +} + int sd_rtnl_send(sd_rtnl *nl, sd_rtnl_message *message, uint32_t *serial) { @@ -149,10 +172,9 @@ int sd_rtnl_send(sd_rtnl *nl, assert_return(nl, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); assert_return(message, -EINVAL); + assert_return(!message->sealed, -EPERM); - r = rtnl_message_seal(nl, message); - if (r < 0) - return r; + rtnl_seal_message(nl, message); if (nl->wqueue_size <= 0) { /* send directly */ @@ -205,10 +227,8 @@ static int dispatch_rqueue(sd_rtnl *rtnl, sd_rtnl_message **message) { /* Try to read a new message */ r = socket_read_message(rtnl, &z); - if (r < 0) + if (r <= 0) return r; - if (r == 0) - return 0; *message = z; @@ -789,7 +809,7 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { if (r < 0) goto fail; - r = sd_event_add_monotonic(rtnl->event, &rtnl->time_event_source, 0, 0, time_callback, rtnl); + r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl); if (r < 0) goto fail;