These are the counterpart of "floating" bus slots, i.e. event sources
that are bound to the lifetime of the event object itself, and thus
don't require an explicit reference to be kept.
};
typedef enum BusSlotType {
};
typedef enum BusSlotType {
- _BUS_SLOT_DISCONNECTED,
BUS_REPLY_CALLBACK,
BUS_FILTER_CALLBACK,
BUS_MATCH_CALLBACK,
BUS_REPLY_CALLBACK,
BUS_FILTER_CALLBACK,
BUS_MATCH_CALLBACK,
BUS_NODE_ENUMERATOR,
BUS_NODE_VTABLE,
BUS_NODE_OBJECT_MANAGER,
BUS_NODE_ENUMERATOR,
BUS_NODE_VTABLE,
BUS_NODE_OBJECT_MANAGER,
+ _BUS_SLOT_INVALID = -1,
} BusSlotType;
struct sd_bus_slot {
unsigned n_ref;
sd_bus *bus;
void *userdata;
} BusSlotType;
struct sd_bus_slot {
unsigned n_ref;
sd_bus *bus;
void *userdata;
- BusSlotType type;
- bool floating;
+ BusSlotType type:5;
+ bool floating:1;
LIST_FIELDS(sd_bus_slot, slots);
LIST_FIELDS(sd_bus_slot, slots);
- switch (slot->type) {
-
- case _BUS_SLOT_DISCONNECTED:
- /* Already disconnected... */
+ switch (slot->type) {
+
case BUS_REPLY_CALLBACK:
if (slot->reply_callback.cookie != 0)
case BUS_REPLY_CALLBACK:
if (slot->reply_callback.cookie != 0)
+
+ default:
+ assert_not_reached("Wut? Unknown slot type?");
- slot->type = _BUS_SLOT_DISCONNECTED;
+ slot->type = _BUS_SLOT_INVALID;
slot->bus = NULL;
LIST_REMOVE(slots, bus->slots, slot);
slot->bus = NULL;
LIST_REMOVE(slots, bus->slots, slot);
_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
assert_return(slot, NULL);
_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
assert_return(slot, NULL);
- assert_return(slot->type != _BUS_SLOT_DISCONNECTED, NULL);
+ assert_return(slot->type >= 0, NULL);
if (slot->bus->current_slot != slot)
return NULL;
if (slot->bus->current_slot != slot)
return NULL;
#include "time-util.h"
#include "missing.h"
#include "set.h"
#include "time-util.h"
#include "missing.h"
#include "set.h"
SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG,
SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG,
- _SOUFCE_EVENT_SOURCE_TYPE_MAX,
+ _SOURCE_EVENT_SOURCE_TYPE_MAX,
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
int enabled:3;
bool pending:1;
bool dispatching:1;
int enabled:3;
bool pending:1;
bool dispatching:1;
int64_t priority;
unsigned pending_index;
int64_t priority;
unsigned pending_index;
unsigned pending_iteration;
unsigned prepare_iteration;
unsigned pending_iteration;
unsigned prepare_iteration;
+ LIST_FIELDS(sd_event_source, sources);
+
union {
struct {
sd_event_io_handler_t callback;
union {
struct {
sd_event_io_handler_t callback;
usec_t watchdog_last, watchdog_period;
unsigned n_sources;
usec_t watchdog_last, watchdog_period;
unsigned n_sources;
+
+ LIST_HEAD(sd_event_source, sources);
+static void source_disconnect(sd_event_source *s);
+
static int pending_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
static int pending_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
}
static void event_free(sd_event *e) {
}
static void event_free(sd_event *e) {
+
+ while ((s = e->sources)) {
+ assert(s->floating);
+ source_disconnect(s);
+ sd_event_source_unref(s);
+ }
+
assert(e->n_sources == 0);
if (e->default_event_ptr)
assert(e->n_sources == 0);
if (e->default_event_ptr)
-static void source_free(sd_event_source *s) {
+static void source_disconnect(sd_event_source *s) {
+ sd_event *event;
+
- if (s->event) {
- assert(s->event->n_sources > 0);
+ if (!s->event)
+ return;
+ assert(s->event->n_sources > 0);
- case SOURCE_IO:
- if (s->io.fd >= 0)
- source_io_unregister(s);
+ case SOURCE_IO:
+ if (s->io.fd >= 0)
+ source_io_unregister(s);
- case SOURCE_TIME_REALTIME:
- case SOURCE_TIME_MONOTONIC:
- case SOURCE_TIME_REALTIME_ALARM:
- case SOURCE_TIME_BOOTTIME_ALARM: {
- struct clock_data *d;
- d = event_get_clock_data(s->event, s->type);
- assert(d);
+ case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_MONOTONIC:
+ case SOURCE_TIME_REALTIME_ALARM:
+ case SOURCE_TIME_BOOTTIME_ALARM: {
+ struct clock_data *d;
- prioq_remove(d->earliest, s, &s->time.earliest_index);
- prioq_remove(d->latest, s, &s->time.latest_index);
- break;
+ d = event_get_clock_data(s->event, s->type);
+ assert(d);
+
+ prioq_remove(d->earliest, s, &s->time.earliest_index);
+ prioq_remove(d->latest, s, &s->time.latest_index);
+ break;
+ }
+
+ case SOURCE_SIGNAL:
+ if (s->signal.sig > 0) {
+ if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0)
+ assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
+
+ if (s->event->signal_sources)
+ s->event->signal_sources[s->signal.sig] = NULL;
- case SOURCE_SIGNAL:
- if (s->signal.sig > 0) {
- if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0)
- assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
- if (s->event->signal_sources)
- s->event->signal_sources[s->signal.sig] = NULL;
+ case SOURCE_CHILD:
+ if (s->child.pid > 0) {
+ if (s->enabled != SD_EVENT_OFF) {
+ assert(s->event->n_enabled_child_sources > 0);
+ s->event->n_enabled_child_sources--;
+ if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD])
+ assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
- case SOURCE_CHILD:
- if (s->child.pid > 0) {
- if (s->enabled != SD_EVENT_OFF) {
- assert(s->event->n_enabled_child_sources > 0);
- s->event->n_enabled_child_sources--;
- }
+ hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
+ }
- if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD])
- assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
- hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
- }
+ case SOURCE_DEFER:
+ /* nothing */
+ break;
+ case SOURCE_POST:
+ set_remove(s->event->post_sources, s);
+ break;
- case SOURCE_DEFER:
- /* nothing */
- break;
+ case SOURCE_EXIT:
+ prioq_remove(s->event->exit, s, &s->exit.prioq_index);
+ break;
- case SOURCE_POST:
- set_remove(s->event->post_sources, s);
- break;
+ default:
+ assert_not_reached("Wut? I shouldn't exist.");
+ }
- case SOURCE_EXIT:
- prioq_remove(s->event->exit, s, &s->exit.prioq_index);
- break;
+ if (s->pending)
+ prioq_remove(s->event->pending, s, &s->pending_index);
- default:
- assert_not_reached("Wut? I shouldn't exist.");
- }
+ if (s->prepare)
+ prioq_remove(s->event->prepare, s, &s->prepare_index);
- if (s->pending)
- prioq_remove(s->event->pending, s, &s->pending_index);
- if (s->prepare)
- prioq_remove(s->event->prepare, s, &s->prepare_index);
+ s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID;
+ s->event = NULL;
+ LIST_REMOVE(sources, event->sources, s);
+ event->n_sources--;
- s->event->n_sources--;
- sd_event_unref(s->event);
- }
+ if (!s->floating)
+ sd_event_unref(event);
+}
+
+static void source_free(sd_event_source *s) {
+ assert(s);
-static sd_event_source *source_new(sd_event *e, EventSourceType type) {
+static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) {
sd_event_source *s;
assert(e);
sd_event_source *s;
assert(e);
return NULL;
s->n_ref = 1;
return NULL;
s->n_ref = 1;
- s->event = sd_event_ref(e);
s->type = type;
s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
s->type = type;
s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
+ s->floating = floating;
+
+ if (!floating)
+ sd_event_ref(e);
+ LIST_PREPEND(sources, e->sources, s);
e->n_sources ++;
return s;
e->n_sources ++;
return s;
assert_return(fd >= 0, -EINVAL);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(fd >= 0, -EINVAL);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- s = source_new(e, SOURCE_IO);
+ s = source_new(e, !ret, SOURCE_IO);
int r;
assert_return(e, -EINVAL);
int r;
assert_return(e, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(usec != (uint64_t) -1, -EINVAL);
assert_return(accuracy != (uint64_t) -1, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(usec != (uint64_t) -1, -EINVAL);
assert_return(accuracy != (uint64_t) -1, -EINVAL);
assert_return(callback, -EINVAL);
- s = source_new(e, type);
+ s = source_new(e, !ret, type);
assert_return(e, -EINVAL);
assert_return(sig > 0, -EINVAL);
assert_return(sig < _NSIG, -EINVAL);
assert_return(e, -EINVAL);
assert_return(sig > 0, -EINVAL);
assert_return(sig < _NSIG, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
} else if (e->signal_sources[sig])
return -EBUSY;
} else if (e->signal_sources[sig])
return -EBUSY;
- s = source_new(e, SOURCE_SIGNAL);
+ s = source_new(e, !ret, SOURCE_SIGNAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
return -EBUSY;
if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
return -EBUSY;
- s = source_new(e, SOURCE_CHILD);
+ s = source_new(e, !ret, SOURCE_CHILD);
e->need_process_child = true;
e->need_process_child = true;
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- s = source_new(e, SOURCE_DEFER);
+ s = source_new(e, !ret, SOURCE_DEFER);
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- s = source_new(e, SOURCE_POST);
+ s = source_new(e, !ret, SOURCE_POST);
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(e, -EINVAL);
assert_return(callback, -EINVAL);
- assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- s = source_new(e, SOURCE_EXIT);
+ s = source_new(e, !ret, SOURCE_EXIT);
if (s->dispatching) {
if (s->type == SOURCE_IO)
source_io_unregister(s);
if (s->dispatching) {
if (s->type == SOURCE_IO)
source_io_unregister(s);
+
+ source_disconnect(s);
break;
case SOURCE_WATCHDOG:
break;
case SOURCE_WATCHDOG:
- case _SOUFCE_EVENT_SOURCE_TYPE_MAX:
+ case _SOURCE_EVENT_SOURCE_TYPE_MAX:
case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
assert_not_reached("Wut? I shouldn't exist.");
}
case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
assert_not_reached("Wut? I shouldn't exist.");
}
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
+ /* Test for floating event sources */
+ assert_se(sigprocmask_many(SIG_BLOCK, SIGRTMIN+1, -1) == 0);
+ assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
+
assert_se(write(a[1], &ch, 1) >= 0);
assert_se(write(b[1], &ch, 1) >= 0);
assert_se(write(a[1], &ch, 1) >= 0);
assert_se(write(b[1], &ch, 1) >= 0);