X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fsd-bus.c;h=0fadd1699e89b9910cc664ab3d63c5723de6e506;hb=b5af2aca120f1bf13cffc270803c2232918dd967;hp=1f1a4d3a1425f2830ff82b0c64f5bd0518dbc530;hpb=2915234da0c9f2f8727d91f04857e7b72d6721a9;p=elogind.git diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 1f1a4d3a1..0fadd1699 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -75,12 +75,6 @@ static void bus_close_fds(sd_bus *b) { static void bus_reset_queues(sd_bus *b) { assert(b); - /* NOTE: We _must_ decrement b->Xqueue_size before calling - * sd_bus_message_unref() for _each_ message. Otherwise the - * self-reference checks in sd_bus_unref() will fire for each message. - * We would thus recurse into sd_bus_message_unref() and trigger the - * assert(m->n_ref > 0) */ - while (b->rqueue_size > 0) sd_bus_message_unref(b->rqueue[--b->rqueue_size]); @@ -1039,8 +1033,10 @@ _public_ int sd_bus_start(sd_bus *bus) { else return -EINVAL; - if (r < 0) + if (r < 0) { + sd_bus_close(bus); return r; + } return bus_send_hello(bus); } @@ -1215,15 +1211,38 @@ fail: int bus_set_address_system_remote(sd_bus *b, const char *host) { _cleanup_free_ char *e = NULL; + char *m = NULL, *c = NULL; assert(b); assert(host); - e = bus_address_escape(host); - if (!e) - return -ENOMEM; + /* Let's see if we shall enter some container */ + m = strchr(host, ':'); + if (m) { + m++; + + /* Let's make sure this is not a port of some kind, + * and is a valid machine name. */ + if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) { + char *t; - b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL); + /* Cut out the host part */ + t = strndupa(host, m - host - 1); + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + + c = strappenda(",argv4=--machine=", m); + } + } + + if (!e) { + e = bus_address_escape(host); + if (!e) + return -ENOMEM; + } + + b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c, NULL); if (!b->address) return -ENOMEM; @@ -1364,53 +1383,6 @@ _public_ sd_bus *sd_bus_unref(sd_bus *bus) { if (!bus) return NULL; - /* TODO/FIXME: It's naive to think REFCNT_GET() is thread-safe in any - * way but exclusive REFCNT_DEC(). The current logic _must_ lock around - * REFCNT_GET() until REFCNT_DEC() or two threads might end up in - * parallel in bus_reset_queues(). But locking would totally break the - * recursion we introduce by bus_reset_queues()... - * (Imagine one thread in sd_bus_message_unref() setting n_ref to 0 and - * thus calling into sd_bus_unref(). If at the same time the real - * thread calls sd_bus_unref(), both end up with "q == true" and will - * call into bus_reset_queues(). - * If we require the main bus to be alive until all dispatch threads - * are done, there is no need to do ref-counts at all. So in both ways, - * the REFCNT thing is humbug.) - * - * On a second note: messages are *not* required to have ->bus set nor - * does it have to be _this_ bus that they're assigned to. This whole - * ref-cnt checking breaks apart if a message is not assigned to us. - * (which is _very_ easy to trigger with the current API). */ - - if (REFCNT_GET(bus->n_ref) == bus->rqueue_size + bus->wqueue_size + 1) { - bool q = true; - - for (i = 0; i < bus->rqueue_size; i++) - if (bus->rqueue[i]->n_ref > 1) { - q = false; - break; - } - - if (q) { - for (i = 0; i < bus->wqueue_size; i++) - if (bus->wqueue[i]->n_ref > 1) { - q = false; - break; - } - } - - /* We are the only holders on the messages, and the - * messages are the only holders on us, so let's drop - * the messages and thus implicitly also kill our own - * last references. - * bus_reset_queues() decrements the queue-size before - * calling into sd_bus_message_unref(). Thus, it - * protects us from recursion. */ - - if (q) - bus_reset_queues(bus); - } - i = REFCNT_DEC(bus->n_ref); if (i > 0) return NULL; @@ -2674,7 +2646,7 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) { struct pollfd p[2] = {}; int r, e, n; struct timespec ts; - usec_t m = (usec_t) -1; + usec_t m = USEC_INFINITY; assert(bus); @@ -2993,6 +2965,7 @@ static int quit_callback(sd_event_source *event, void *userdata) { assert(event); sd_bus_flush(bus); + sd_bus_close(bus); return 1; }