chiark / gitweb /
sd-event: simplify sd_event_source_set_name()
[elogind.git] / src / libsystemd / sd-event / sd-event.c
index 7917ab934ae4f233732180be5e70c72266cf1224..985ff2829bdbab1baa8b74fbb479b779d5f93992 100644 (file)
@@ -66,6 +66,8 @@ struct sd_event_source {
         void *userdata;
         sd_event_handler_t prepare;
 
+        char *name;
+
         EventSourceType type:5;
         int enabled:3;
         bool pending:1;
@@ -685,6 +687,7 @@ static void source_free(sd_event_source *s) {
         assert(s);
 
         source_disconnect(s);
+        free(s->name);
         free(s);
 }
 
@@ -1223,6 +1226,21 @@ _public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
         return NULL;
 }
 
+_public_ int sd_event_source_set_name(sd_event_source *s, const char *name) {
+        assert_return(s, -EINVAL);
+
+        return free_and_strdup(&s->name, name);
+}
+
+_public_ int sd_event_source_get_name(sd_event_source *s, const char **name) {
+        assert_return(s, -EINVAL);
+        assert_return(name, -EINVAL);
+
+        *name = s->name;
+
+        return 0;
+}
+
 _public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
         assert_return(s, NULL);
 
@@ -2083,8 +2101,12 @@ static int source_dispatch(sd_event_source *s) {
 
         s->dispatching = false;
 
-        if (r < 0)
-                log_debug("Event source %p returned error, disabling: %s", s, strerror(-r));
+        if (r < 0) {
+                if (s->name)
+                        log_debug("Event source '%s' returned error, disabling: %s", s->name, strerror(-r));
+                else
+                        log_debug("Event source %p returned error, disabling: %s", s, strerror(-r));
+        }
 
         if (s->n_ref == 0)
                 source_free(s);
@@ -2117,8 +2139,12 @@ static int event_prepare(sd_event *e) {
                 r = s->prepare(s, s->userdata);
                 s->dispatching = false;
 
-                if (r < 0)
-                        log_debug("Prepare callback of event source %p returned error, disabling: %s", s, strerror(-r));
+                if (r < 0) {
+                        if (s->name)
+                                log_debug("Prepare callback of event source '%s' returned error, disabling: %s", s->name, strerror(-r));
+                        else
+                                log_debug("Prepare callback of event source %p returned error, disabling: %s", s, strerror(-r));
+                }
 
                 if (s->n_ref == 0)
                         source_free(s);
@@ -2210,12 +2236,8 @@ static int process_watchdog(sd_event *e) {
         return arm_watchdog(e);
 }
 
-_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
-        struct epoll_event *ev_queue;
-        unsigned ev_queue_max;
-        sd_event_source *p;
-        int r, i, m;
-        bool timedout;
+_public_ int sd_event_prepare(sd_event *e) {
+        int r;
 
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
@@ -2223,38 +2245,64 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
 
         if (e->exit_requested)
-                return dispatch_exit(e);
+                goto pending;
 
-        sd_event_ref(e);
         e->iteration++;
-        e->state = SD_EVENT_RUNNING;
 
         r = event_prepare(e);
         if (r < 0)
-                goto finish;
+                return r;
 
         r = event_arm_timer(e, &e->realtime);
         if (r < 0)
-                goto finish;
+                return r;
 
         r = event_arm_timer(e, &e->boottime);
         if (r < 0)
-                goto finish;
+                return r;
 
         r = event_arm_timer(e, &e->monotonic);
         if (r < 0)
-                goto finish;
+                return r;
 
         r = event_arm_timer(e, &e->realtime_alarm);
         if (r < 0)
-                goto finish;
+                return r;
 
         r = event_arm_timer(e, &e->boottime_alarm);
         if (r < 0)
-                goto finish;
+                return r;
 
         if (event_next_pending(e) || e->need_process_child)
-                timeout = 0;
+                goto pending;
+
+        e->state = SD_EVENT_PREPARED;
+
+        return 0;
+
+pending:
+        e->state = SD_EVENT_PREPARED;
+        r = sd_event_wait(e, 0);
+        if (r == 0)
+                e->state = SD_EVENT_PREPARED;
+
+        return r;
+}
+
+_public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
+        struct epoll_event *ev_queue;
+        unsigned ev_queue_max;
+        int r, m, i;
+
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+        assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+        assert_return(e->state == SD_EVENT_PREPARED, -EBUSY);
+
+        if (e->exit_requested) {
+                e->state = SD_EVENT_PENDING;
+                return 1;
+        }
 
         ev_queue_max = CLAMP(e->n_sources, 1U, EPOLL_QUEUE_MAX);
         ev_queue = newa(struct epoll_event, ev_queue_max);
@@ -2262,12 +2310,16 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
                        timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
         if (m < 0) {
-                r = errno == EAGAIN || errno == EINTR ? 1 : -errno;
+                if (errno == EINTR) {
+                        e->state = SD_EVENT_PENDING;
+                        return 1;
+                }
+
+                r = -errno;
+
                 goto finish;
         }
 
-        timedout = m == 0;
-
         dual_timestamp_get(&e->timestamp);
         e->timestamp_boottime = now(CLOCK_BOOTTIME);
 
@@ -2324,21 +2376,71 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
                         goto finish;
         }
 
-        p = event_next_pending(e);
-        if (!p) {
-                r = !timedout;
-                goto finish;
+        if (event_next_pending(e)) {
+                e->state = SD_EVENT_PENDING;
+
+                return 1;
         }
 
-        r = source_dispatch(p);
+        r = 0;
 
 finish:
         e->state = SD_EVENT_PASSIVE;
-        sd_event_unref(e);
 
         return r;
 }
 
+_public_ int sd_event_dispatch(sd_event *e) {
+        sd_event_source *p;
+        int r;
+
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+        assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+        assert_return(e->state == SD_EVENT_PENDING, -EBUSY);
+
+        if (e->exit_requested)
+                return dispatch_exit(e);
+
+        p = event_next_pending(e);
+        if (p) {
+                sd_event_ref(e);
+
+                e->state = SD_EVENT_RUNNING;
+                r = source_dispatch(p);
+                e->state = SD_EVENT_PASSIVE;
+
+                sd_event_unref(e);
+
+                return r;
+        }
+
+        e->state = SD_EVENT_PASSIVE;
+
+        return 1;
+}
+
+_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
+        int r;
+
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+        assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+        assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
+
+        r = sd_event_prepare(e);
+        if (r > 0)
+                return sd_event_dispatch(e);
+        else if (r < 0)
+                return r;
+
+        r = sd_event_wait(e, timeout);
+        if (r > 0)
+                return sd_event_dispatch(e);
+        else
+                return r;
+}
+
 _public_ int sd_event_loop(sd_event *e) {
         int r;
 
@@ -2361,6 +2463,14 @@ finish:
         return r;
 }
 
+_public_ int sd_event_get_fd(sd_event *e) {
+
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+
+        return e->epoll_fd;
+}
+
 _public_ int sd_event_get_state(sd_event *e) {
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);