summaryrefslogtreecommitdiffstats
path: root/src/import/curl-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/curl-util.c')
-rw-r--r--src/import/curl-util.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 94f718d..1628f83 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -10,20 +10,28 @@
#include "version.h"
static void curl_glue_check_finished(CurlGlue *g) {
- CURLMsg *msg;
- int k = 0;
+ int r;
assert(g);
+ /* sd_event_get_exit_code() returns -ENODATA if no exit was scheduled yet */
+ r = sd_event_get_exit_code(g->event, /* ret_code= */ NULL);
+ if (r >= 0)
+ return; /* exit scheduled? Then don't process this anymore */
+ if (r != -ENODATA)
+ log_debug_errno(r, "Unexpected error while checking for event loop exit code, ignoring: %m");
+
+ CURLMsg *msg;
+ int k = 0;
msg = curl_multi_info_read(g->curl, &k);
if (!msg)
return;
- if (msg->msg != CURLMSG_DONE)
- return;
-
- if (g->on_finished)
+ if (msg->msg == CURLMSG_DONE && g->on_finished)
g->on_finished(g, msg->easy_handle, msg->data.result);
+
+ /* This is a queue, process another item soon, but do so in a later event loop iteration. */
+ (void) sd_event_source_set_enabled(g->defer, SD_EVENT_ONESHOT);
}
static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@@ -126,6 +134,13 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
assert(curl);
+ /* Don't configure timer anymore when the event loop is dead already. */
+ if (g->timer) {
+ sd_event *event_loop = sd_event_source_get_event(g->timer);
+ if (event_loop && sd_event_get_state(event_loop) == SD_EVENT_FINISHED)
+ return 0;
+ }
+
if (timeout_ms < 0) {
if (g->timer) {
if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
@@ -153,6 +168,15 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
return 0;
}
+static int curl_glue_on_defer(sd_event_source *s, void *userdata) {
+ CurlGlue *g = ASSERT_PTR(userdata);
+
+ assert(s);
+
+ curl_glue_check_finished(g);
+ return 0;
+}
+
CurlGlue *curl_glue_unref(CurlGlue *g) {
sd_event_source *io;
@@ -167,7 +191,8 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
hashmap_free(g->ios);
- sd_event_source_unref(g->timer);
+ sd_event_source_disable_unref(g->timer);
+ sd_event_source_disable_unref(g->defer);
sd_event_unref(g->event);
return mfree(g);
}
@@ -211,6 +236,12 @@ int curl_glue_new(CurlGlue **glue, sd_event *event) {
if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
return -EINVAL;
+ r = sd_event_add_defer(g->event, &g->defer, curl_glue_on_defer, g);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_source_set_description(g->defer, "curl-defer");
+
*glue = TAKE_PTR(g);
return 0;