]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-event: store and compare per-module static origin id 27347/head
authorLuca Boccassi <bluca@debian.org>
Tue, 25 Apr 2023 00:46:22 +0000 (01:46 +0100)
committerLuca Boccassi <bluca@debian.org>
Tue, 25 Apr 2023 11:24:25 +0000 (12:24 +0100)
sd-event objects use hashmaps, which use module-global state, so it is not safe
to pass a sd-event object created by a module instance to another module instance
(e.g.: when two libraries static linking sd-event are pulled in a single process).
Initialize a random per-module origin id and store it in the object, and compare
it when entering a public API, and error out if they don't match, together with
the PID.

23 files changed:
man/sd_event_add_child.xml
man/sd_event_add_defer.xml
man/sd_event_add_inotify.xml
man/sd_event_add_io.xml
man/sd_event_add_memory_pressure.xml
man/sd_event_add_signal.xml
man/sd_event_add_time.xml
man/sd_event_exit.xml
man/sd_event_get_fd.xml
man/sd_event_now.xml
man/sd_event_run.xml
man/sd_event_set_signal_exit.xml
man/sd_event_set_watchdog.xml
man/sd_event_source_get_pending.xml
man/sd_event_source_set_description.xml
man/sd_event_source_set_enabled.xml
man/sd_event_source_set_floating.xml
man/sd_event_source_set_prepare.xml
man/sd_event_source_set_priority.xml
man/sd_event_source_set_ratelimit.xml
man/sd_event_wait.xml
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-event/test-event.c

index fec754d2ddec7847b9681f9f5eff63dc5f703931..31b9d7634026cba1807654487688a89b22fb3298 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index e56e16a0328d8ae6d247c28690b8f5c07e4578aa..3bac5d53d424baeea4f11a18686dc2ec59ae7368 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
       </variablelist>
index c7af7bdcd00e16504c4a77c5d4e3646c7f41e74c..1f31907b0db1be02c257acde7d34951565129c45 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index 383a58a074e354334d622eed471dd0193c4bbdbf..4201c68f0d0db624df35676821f8f13014f4ef1d 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 8df69fde3bb2be92e6a2ec0b29875a39d024f6b2..08a27d15c1b6f481bf53df5110d4f444c5a1dbf9 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 3e8536e96112bdcd60a6c1ff22cdd49860050ec3..29a782397404d3d68f6e1153950feb0f84b1b963 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 19f112b0f6033ca21ce12572730928ea72a61b1a..6031fee1b38b0cdd71a4cec3b4d52aa741d1ccb1 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index e13cbe18ab9d499942c47d3fac94931edd855fa4..343dd9066e148d30cf2e16b0165525ed95df489d 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop was created in a different process.</para></listitem>
+          <listitem><para>The event loop was created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index a3b11e41ee3cd0af78ba3126b00ba0a429a293f0..698691fa0d200f96bf6d8c42a3b3ec73b631b266 100644 (file)
@@ -77,7 +77,7 @@
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
       </variablelist>
index 789b9e028847ac6c4b3f9e5fa52bf6eb950cb692..70e980ab7b3ea0646287d89246d3bfc14567da3a 100644 (file)
@@ -91,7 +91,7 @@
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop object was created in a different process.</para></listitem>
+          <listitem><para>The event loop object was created in a different process, library or module instance.</para></listitem>
         </varlistentry>
       </variablelist>
     </refsect2>
index 81c51b7060393416f65a6f4bdf2fbf1d06c0aee6..c30f5eb4c231d2c073df52ed83af6e50cd2ab889 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index e5e675beec9ec761c73be93dfab4048e8b9d70d8..cdf49a54f9c58511e53e672da517d82f6288a6fd 100644 (file)
@@ -72,7 +72,7 @@
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 28d647c7bcdea49f72e234871e793d15b4fa506f..954a1366cf6dfda90bbf5cf4a762058242e16910 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 5906930b3c3be64cc4f6b16c1df042115eeba570..7521ba6420c0e57bdea3114b76a5c6bb953e7f23 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index bea3e71914e571f71be5a0befb4e8389d6d14f46..9ad369817f87fa795312d2bf6201aa58ccb25c42 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index 5f13fc101d0d923465139a2f2b32482b033121f6..cab8667f0fe5c5e0669969b05f3d6350c38756b5 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index 7f3ed86a6585ff0bfe9a4b58f08485ef28379a56..db288094b67169006e45d99e6ddb5faed3760bff 100644 (file)
@@ -89,7 +89,7 @@
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index d52c55b3db950c42bb563a9d00cb1fb8d7f3a68d..e7526a9ff5aa51083a50f234c18879be51827122 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index 2616c12e3fc7aed942fef68d89439d0e1348f714..efe05b11d26643aed3f992b49f2918f72c7581c4 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index b8e6380ddd39ebc6e1170d9b4cb5bcdf3979d433..07ac18b7917fb1d173d9091caab37590ac5f0845 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 25e21b9d5cfbf52b00538343f171c65b42d2db61..0dc7105cf9cde7551630259476aed1dd1765fed3 100644 (file)
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
-          <listitem><para>The event loop has been created in a different process.</para></listitem>
+          <listitem><para>The event loop has been created in a different process, library or module instance.</para></listitem>
 
         </varlistentry>
 
index f11f35ef6e858677447a4382586b0b0da9a164de..a12d5e1a5a5ec0fe0d819d9cdb6de7a3cb38efdf 100644 (file)
@@ -25,6 +25,7 @@
 #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"
@@ -144,7 +145,7 @@ struct sd_event {
         /* 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;
@@ -174,6 +175,8 @@ struct sd_event {
         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);
@@ -410,7 +413,7 @@ _public_ int sd_event_new(sd_event** ret) {
                 .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);
@@ -439,7 +442,31 @@ fail:
         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);
 
@@ -449,20 +476,11 @@ _public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
         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)
@@ -503,7 +521,7 @@ static void source_child_pidfd_unregister(sd_event_source *s) {
         assert(s);
         assert(s->type == SOURCE_CHILD);
 
-        if (event_pid_changed(s->event))
+        if (event_origin_changed(s->event))
                 return;
 
         if (!s->child.registered)
@@ -542,7 +560,7 @@ static void source_memory_pressure_unregister(sd_event_source *s) {
         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)
@@ -694,7 +712,7 @@ static int event_make_signal_data(
 
         assert(e);
 
-        if (event_pid_changed(e))
+        if (event_origin_changed(e))
                 return -ECHILD;
 
         if (e->signal_sources && e->signal_sources[sig])
@@ -791,7 +809,7 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig
                 return;
         }
 
-        if (event_pid_changed(e))
+        if (event_origin_changed(e))
                 return;
 
         assert(d->fd >= 0);
@@ -954,7 +972,7 @@ static void source_disconnect(sd_event_source *s) {
                 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) {
@@ -1231,7 +1249,7 @@ _public_ int sd_event_add_io(
         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;
@@ -1378,7 +1396,7 @@ _public_ int sd_event_add_time(
         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;
@@ -1465,7 +1483,7 @@ _public_ int sd_event_add_signal(
         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);
@@ -1575,7 +1593,7 @@ _public_ int sd_event_add_child(
         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;
@@ -1673,7 +1691,7 @@ _public_ int sd_event_add_child_pidfd(
         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;
@@ -1754,7 +1772,7 @@ _public_ int sd_event_add_defer(
         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;
@@ -1790,7 +1808,7 @@ _public_ int sd_event_add_post(
         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;
@@ -1828,7 +1846,7 @@ _public_ int sd_event_add_exit(
         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)
@@ -1928,7 +1946,7 @@ _public_ int sd_event_add_memory_pressure(
         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;
@@ -2126,7 +2144,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
         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");
 
@@ -2237,7 +2255,7 @@ static void event_free_inode_data(
         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
@@ -2444,7 +2462,7 @@ static int event_add_inotify_fd_internal(
         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;
@@ -2577,7 +2595,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event_source, sd_event_source, event_sou
 
 _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);
 }
@@ -2585,7 +2603,7 @@ _public_ int sd_event_source_set_description(sd_event_source *s, const char *des
 _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;
@@ -2596,6 +2614,7 @@ _public_ int sd_event_source_get_description(sd_event_source *s, const char **de
 
 _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;
 }
@@ -2604,7 +2623,7 @@ _public_ int sd_event_source_get_pending(sd_event_source *s) {
         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;
 }
@@ -2612,7 +2631,7 @@ _public_ int sd_event_source_get_pending(sd_event_source *s) {
 _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;
 }
@@ -2623,7 +2642,7 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int 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;
@@ -2656,6 +2675,7 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) {
 _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;
 }
@@ -2663,6 +2683,7 @@ _public_ int sd_event_source_get_io_fd_own(sd_event_source *s) {
 _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;
@@ -2672,7 +2693,7 @@ _public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events)
         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;
@@ -2685,7 +2706,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
         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))
@@ -2711,7 +2732,7 @@ _public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revent
         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;
@@ -2720,14 +2741,14 @@ _public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revent
 _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;
@@ -2741,7 +2762,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
 
         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;
@@ -2841,7 +2862,7 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *ret) {
                 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;
@@ -3035,7 +3056,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
                 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)
@@ -3067,7 +3088,7 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
         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;
@@ -3079,7 +3100,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         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)
@@ -3097,6 +3118,7 @@ _public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec
 
         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);
@@ -3116,7 +3138,7 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
         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;
@@ -3129,7 +3151,7 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
         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)
@@ -3148,7 +3170,7 @@ _public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock
         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;
@@ -3158,7 +3180,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         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;
@@ -3167,7 +3189,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
 _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;
@@ -3178,7 +3200,7 @@ _public_ int sd_event_source_get_child_pidfd(sd_event_source *s) {
 _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
@@ -3223,6 +3245,7 @@ _public_ int sd_event_source_send_child_signal(sd_event_source *s, int sig, cons
 _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;
@@ -3233,6 +3256,7 @@ _public_ int sd_event_source_get_child_pidfd_own(sd_event_source *s) {
 _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;
@@ -3244,6 +3268,7 @@ _public_ int sd_event_source_set_child_pidfd_own(sd_event_source *s, int own) {
 _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;
 }
@@ -3251,6 +3276,7 @@ _public_ int sd_event_source_get_child_process_own(sd_event_source *s) {
 _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;
@@ -3260,7 +3286,7 @@ _public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask
         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;
@@ -3272,7 +3298,7 @@ _public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t
         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;
@@ -3300,6 +3326,7 @@ _public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t
 
 _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;
 }
@@ -3308,6 +3335,7 @@ _public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata)
         void *ret;
 
         assert_return(s, NULL);
+        assert_return(!event_origin_changed(s->event), NULL);
 
         ret = s->userdata;
         s->userdata = userdata;
@@ -4423,7 +4451,7 @@ _public_ int sd_event_prepare(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);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
 
@@ -4662,7 +4690,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
 
         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);
 
@@ -4765,7 +4793,7 @@ _public_ int sd_event_dispatch(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);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(e->state == SD_EVENT_PENDING, -EBUSY);
 
@@ -4805,7 +4833,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
 
         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);
 
@@ -4853,9 +4881,10 @@ _public_ int sd_event_loop(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);
         assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
 
+
         PROTECT_EVENT(e);
 
         while (e->state != SD_EVENT_FINISHED) {
@@ -4870,7 +4899,7 @@ _public_ int sd_event_loop(sd_event *e) {
 _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;
 }
@@ -4878,7 +4907,7 @@ _public_ int sd_event_get_fd(sd_event *e) {
 _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;
 }
@@ -4887,7 +4916,7 @@ _public_ int sd_event_get_exit_code(sd_event *e, int *code) {
         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;
@@ -4900,7 +4929,7 @@ _public_ int sd_event_exit(sd_event *e, int code) {
         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;
@@ -4912,7 +4941,7 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
         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;
@@ -4955,7 +4984,7 @@ _public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
         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;
@@ -4970,7 +4999,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
 
         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;
@@ -5020,7 +5049,7 @@ fail:
 _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;
 }
@@ -5028,7 +5057,7 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
 _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;
@@ -5036,6 +5065,8 @@ _public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
 
 _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;
@@ -5043,6 +5074,7 @@ _public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_d
 
 _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;
@@ -5052,12 +5084,14 @@ _public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_d
 
 _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;
@@ -5081,6 +5115,7 @@ _public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
 _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;
 }
@@ -5088,6 +5123,7 @@ _public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) {
 _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;
@@ -5100,6 +5136,7 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval
         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. */
@@ -5117,6 +5154,7 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval
 
 _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;
@@ -5124,6 +5162,7 @@ _public_ int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, s
 
 _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. */
@@ -5143,6 +5182,7 @@ _public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_int
 
 _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;
@@ -5212,6 +5252,7 @@ _public_ int sd_event_source_set_memory_pressure_type(sd_event_source *s, const
         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;
@@ -5253,6 +5294,7 @@ _public_ int sd_event_source_set_memory_pressure_period(sd_event_source *s, uint
 
         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;
index 591eab8896e97a542e579c46f32a52636c3f7bb4..4f61af50f339ef046ad4eac9ee926f3bc97e047b 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include "sd-event.h"
 
@@ -808,4 +809,23 @@ TEST(inotify_process_buffered_data) {
         assert_se(sd_event_wait(e, 0) == 0);
 }
 
+TEST(fork) {
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        int r;
+
+        assert_se(sd_event_default(&e) >= 0);
+        assert_se(sd_event_prepare(e) == 0);
+
+        /* Check that after a fork the cleanup functions return NULL */
+        r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
+        if (r == 0) {
+                assert_se(e);
+                assert_se(sd_event_ref(e) == NULL);
+                assert_se(sd_event_unref(e) == NULL);
+                _exit(EXIT_SUCCESS);
+        }
+
+        assert_se(r >= 0);
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);