mirror of
https://github.com/systemd/systemd
synced 2024-07-23 19:25:39 +00:00
curl-util: fix downloads from file:// URLs
if we try to open file:// URLs that don't exist, we'll not get IO/timer events about it, hence it is not sufficient to check for completion in these events. Let's add a defer event, to deal with that. Also, curl_multi_info_read() is a queue, make sure to handle all events that might be queued.
This commit is contained in:
parent
7253eaa0fb
commit
8bd4d506a4
|
@ -10,20 +10,28 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
static void curl_glue_check_finished(CurlGlue *g) {
|
static void curl_glue_check_finished(CurlGlue *g) {
|
||||||
CURLMsg *msg;
|
int r;
|
||||||
int k = 0;
|
|
||||||
|
|
||||||
assert(g);
|
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);
|
msg = curl_multi_info_read(g->curl, &k);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (msg->msg != CURLMSG_DONE)
|
if (msg->msg == CURLMSG_DONE && g->on_finished)
|
||||||
return;
|
|
||||||
|
|
||||||
if (g->on_finished)
|
|
||||||
g->on_finished(g, msg->easy_handle, msg->data.result);
|
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) {
|
static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||||
|
@ -153,6 +161,15 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
|
||||||
return 0;
|
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) {
|
CurlGlue *curl_glue_unref(CurlGlue *g) {
|
||||||
sd_event_source *io;
|
sd_event_source *io;
|
||||||
|
|
||||||
|
@ -167,7 +184,8 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
|
||||||
|
|
||||||
hashmap_free(g->ios);
|
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);
|
sd_event_unref(g->event);
|
||||||
return mfree(g);
|
return mfree(g);
|
||||||
}
|
}
|
||||||
|
@ -211,6 +229,12 @@ int curl_glue_new(CurlGlue **glue, sd_event *event) {
|
||||||
if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
|
if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
|
||||||
return -EINVAL;
|
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);
|
*glue = TAKE_PTR(g);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct CurlGlue {
|
||||||
CURLM *curl;
|
CURLM *curl;
|
||||||
sd_event_source *timer;
|
sd_event_source *timer;
|
||||||
Hashmap *ios;
|
Hashmap *ios;
|
||||||
|
sd_event_source *defer;
|
||||||
|
|
||||||
void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code);
|
void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code);
|
||||||
void *userdata;
|
void *userdata;
|
||||||
|
|
Loading…
Reference in a new issue