#include "missing_magic.h"
#include "missing_syscall.h"
#include "missing_threads.h"
+#include "origin-id.h"
#include "path-util.h"
#include "prioq.h"
#include "process-util.h"
/* A list of memory pressure event sources that still need their subscription string written */
LIST_HEAD(sd_event_source, memory_pressure_write_list);
- pid_t original_pid;
+ uint64_t origin_id;
uint64_t iteration;
triple_timestamp timestamp;
unsigned delays[sizeof(usec_t) * 8];
};
+DEFINE_PRIVATE_ORIGIN_ID_HELPERS(sd_event, event);
+
static thread_local sd_event *default_event = NULL;
static void source_disconnect(sd_event_source *s);
.boottime_alarm.fd = -EBADF,
.boottime_alarm.next = USEC_INFINITY,
.perturb = USEC_INFINITY,
- .original_pid = getpid_cached(),
+ .origin_id = origin_id_query(),
};
r = prioq_ensure_allocated(&e->pending, pending_prioq_compare);
return r;
}
-DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
+/* Define manually so we can add the origin check */
+_public_ sd_event *sd_event_ref(sd_event *e) {
+ if (!e)
+ return NULL;
+ if (event_origin_changed(e))
+ return NULL;
+
+ e->n_ref++;
+
+ return e;
+}
+
+_public_ sd_event* sd_event_unref(sd_event *e) {
+ if (!e)
+ return NULL;
+ if (event_origin_changed(e))
+ return NULL;
+
+ assert(e->n_ref > 0);
+ if (--e->n_ref > 0)
+ return NULL;
+
+ return event_free(e);
+}
+
#define PROTECT_EVENT(e) \
_unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
return sd_event_source_unref(s);
}
-static bool event_pid_changed(sd_event *e) {
- assert(e);
-
- /* We don't support people creating an event loop and keeping
- * it around over a fork(). Let's complain. */
-
- return e->original_pid != getpid_cached();
-}
-
static void source_io_unregister(sd_event_source *s) {
assert(s);
assert(s->type == SOURCE_IO);
- if (event_pid_changed(s->event))
+ if (event_origin_changed(s->event))
return;
if (!s->io.registered)
assert(s);
assert(s->type == SOURCE_CHILD);
- if (event_pid_changed(s->event))
+ if (event_origin_changed(s->event))
return;
if (!s->child.registered)
assert(s);
assert(s->type == SOURCE_MEMORY_PRESSURE);
- if (event_pid_changed(s->event))
+ if (event_origin_changed(s->event))
return;
if (!s->memory_pressure.registered)
assert(e);
- if (event_pid_changed(e))
+ if (event_origin_changed(e))
return -ECHILD;
if (e->signal_sources && e->signal_sources[sig])
return;
}
- if (event_pid_changed(e))
+ if (event_origin_changed(e))
return;
assert(d->fd >= 0);
break;
case SOURCE_CHILD:
- if (event_pid_changed(s->event))
+ if (event_origin_changed(s->event))
s->child.process_owned = false;
if (s->child.pid > 0) {
assert_return(fd >= 0, -EBADF);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = io_exit_callback;
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(accuracy != UINT64_MAX, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */
return -EOPNOTSUPP;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
/* Let's make sure our special flag stays outside of the valid signal range */
assert_cc(_NSIG < SD_EVENT_SIGNAL_PROCMASK);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = child_exit_callback;
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = child_exit_callback;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = generic_exit_callback;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = generic_exit_callback;
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
r = prioq_ensure_allocated(&e->exit, exit_prioq_compare);
if (r < 0)
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = memory_pressure_callback;
assert_se(hashmap_remove(e->inotify_data, &d->priority) == d);
if (d->fd >= 0) {
- if (!event_pid_changed(e) &&
+ if (!event_origin_changed(e) &&
epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m");
if (d->inotify_data) {
if (d->wd >= 0) {
- if (d->inotify_data->fd >= 0 && !event_pid_changed(e)) {
+ if (d->inotify_data->fd >= 0 && !event_origin_changed(e)) {
/* So here's a problem. At the time this runs the watch descriptor might already be
* invalidated, because an IN_IGNORED event might be queued right the moment we enter
* the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(fd >= 0, -EBADF);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!callback)
callback = inotify_exit_callback;
_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) {
assert_return(s, -EINVAL);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return free_and_strdup(&s->description, description);
}
_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) {
assert_return(s, -EINVAL);
assert_return(description, -EINVAL);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (!s->description)
return -ENXIO;
_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
assert_return(s, NULL);
+ assert_return(!event_origin_changed(s->event), NULL);
return s->event;
}
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->pending;
}
_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->io.fd;
}
assert_return(s, -EINVAL);
assert_return(fd >= 0, -EBADF);
assert_return(s->type == SOURCE_IO, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->io.fd == fd)
return 0;
_public_ int sd_event_source_get_io_fd_own(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->io.owned;
}
_public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
s->io.owned = own;
return 0;
assert_return(s, -EINVAL);
assert_return(events, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*events = s->io.events;
return 0;
assert_return(s->type == SOURCE_IO, -EDOM);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
/* edge-triggered updates are never skipped, so we can reset edges */
if (s->io.events == events && !(events & EPOLLET))
assert_return(revents, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
assert_return(s->pending, -ENODATA);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*revents = s->io.revents;
return 0;
_public_ int sd_event_source_get_signal(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_SIGNAL, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->signal.sig;
}
_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) {
assert_return(s, -EINVAL);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*priority = s->priority;
return 0;
assert_return(s, -EINVAL);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->priority == priority)
return 0;
return false;
assert_return(s, -EINVAL);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (ret)
*ret = s->enabled;
return 0;
assert_return(s, -EINVAL);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
/* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */
if (s->event->state == SD_EVENT_FINISHED)
assert_return(s, -EINVAL);
assert_return(usec, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*usec = s->time.next;
return 0;
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
r = source_set_pending(s, false);
if (r < 0)
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (usec == USEC_INFINITY)
return sd_event_source_set_time(s, USEC_INFINITY);
assert_return(s, -EINVAL);
assert_return(usec, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*usec = s->time.accuracy;
return 0;
assert_return(usec != UINT64_MAX, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
r = source_set_pending(s, false);
if (r < 0)
assert_return(s, -EINVAL);
assert_return(clock, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*clock = event_source_type_to_clock(s->type);
return 0;
assert_return(s, -EINVAL);
assert_return(pid, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*pid = s->child.pid;
return 0;
_public_ int sd_event_source_get_child_pidfd(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->child.pidfd < 0)
return -EOPNOTSUPP;
_public_ int sd_event_source_send_child_signal(sd_event_source *s, int sig, const siginfo_t *si, unsigned flags) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
assert_return(SIGNAL_VALID(sig), -EINVAL);
/* If we already have seen indication the process exited refuse sending a signal early. This way we
_public_ int sd_event_source_get_child_pidfd_own(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->child.pidfd < 0)
return -EOPNOTSUPP;
_public_ int sd_event_source_set_child_pidfd_own(sd_event_source *s, int own) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->child.pidfd < 0)
return -EOPNOTSUPP;
_public_ int sd_event_source_get_child_process_own(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->child.process_owned;
}
_public_ int sd_event_source_set_child_process_own(sd_event_source *s, int own) {
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_CHILD, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
s->child.process_owned = own;
return 0;
assert_return(s, -EINVAL);
assert_return(mask, -EINVAL);
assert_return(s->type == SOURCE_INOTIFY, -EDOM);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
*mask = s->inotify.mask;
return 0;
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(s->event), -ECHILD);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->prepare == callback)
return 0;
_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
assert_return(s, NULL);
+ assert_return(!event_origin_changed(s->event), NULL);
return s->userdata;
}
void *ret;
assert_return(s, NULL);
+ assert_return(!event_origin_changed(s->event), NULL);
ret = s->userdata;
s->userdata = userdata;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_ARMED, -EBUSY);
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_PENDING, -EBUSY);
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
+
PROTECT_EVENT(e);
while (e->state != SD_EVENT_FINISHED) {
_public_ int sd_event_get_fd(sd_event *e) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
return e->epoll_fd;
}
_public_ int sd_event_get_state(sd_event *e) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
return e->state;
}
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(code, -EINVAL);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!e->exit_requested)
return -ENODATA;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
e->exit_requested = true;
e->exit_code = code;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(usec, -EINVAL);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock))
return -EOPNOTSUPP;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(tid, -EINVAL);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (e->tid != 0) {
*tid = e->tid;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
if (e->watchdog == !!b)
return e->watchdog;
_public_ int sd_event_get_watchdog(sd_event *e) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
return e->watchdog;
}
_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(!event_pid_changed(e), -ECHILD);
+ assert_return(!event_origin_changed(e), -ECHILD);
*ret = e->iteration;
return 0;
_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) {
assert_return(s, -EINVAL);
+ assert_return(s->event, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
s->destroy_callback = callback;
return 0;
_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (ret)
*ret = s->destroy_callback;
_public_ int sd_event_source_get_floating(sd_event_source *s) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->floating;
}
_public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->floating == !!b)
return 0;
_public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) {
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
return s->exit_on_failure;
}
_public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) {
assert_return(s, -EINVAL);
assert_return(s->type != SOURCE_EXIT, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (s->exit_on_failure == !!b)
return 0;
int r;
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
/* Turning on ratelimiting on event source types that don't support it, is a loggable offense. Doing
* so is a programming error. */
_public_ int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
s->ratelimit_expire_callback = callback;
return 0;
_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
/* Querying whether an event source has ratelimiting configured is not a loggable offense, hence
* don't use assert_return(). Unlike turning on ratelimiting it's not really a programming error. */
_public_ int sd_event_source_is_ratelimited(sd_event_source *s) {
assert_return(s, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type))
return false;
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_MEMORY_PRESSURE, -EDOM);
assert_return(ty, -EINVAL);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (!STR_IN_SET(ty, "some", "full"))
return -EINVAL;
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_MEMORY_PRESSURE, -EDOM);
+ assert_return(!event_origin_changed(s->event), -ECHILD);
if (threshold_usec <= 0 || threshold_usec >= UINT64_MAX)
return -ERANGE;