Use modern libcurl poll/wait methods

This commit is contained in:
sfan5 2024-01-13 19:14:04 +01:00
parent ee727eb65e
commit 56943bef48
2 changed files with 32 additions and 49 deletions

@ -47,7 +47,7 @@ option(ENABLE_CURL "Enable cURL support for fetching media" TRUE)
set(USE_CURL FALSE) set(USE_CURL FALSE)
if(ENABLE_CURL) if(ENABLE_CURL)
find_package(CURL) find_package(CURL 7.28.0)
if (CURL_FOUND) if (CURL_FOUND)
message(STATUS "cURL support enabled.") message(STATUS "cURL support enabled.")
set(USE_CURL TRUE) set(USE_CURL TRUE)

@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <unordered_map> #include <unordered_map>
#include <cerrno> #include <cerrno>
#include <mutex> #include <mutex>
#include "network/socket.h" // for select()
#include "threading/event.h" #include "threading/event.h"
#include "config.h" #include "config.h"
#include "exceptions.h" #include "exceptions.h"
@ -436,6 +435,12 @@ HTTPFetchOngoing::~HTTPFetchOngoing()
} }
#if LIBCURL_VERSION_NUM >= 0x074200
#define HAVE_CURL_MULTI_POLL
#else
#undef HAVE_CURL_MULTI_POLL
#endif
class CurlFetchThread : public Thread class CurlFetchThread : public Thread
{ {
protected: protected:
@ -595,62 +600,40 @@ protected:
// Wait until some IO happens, or timeout elapses // Wait until some IO happens, or timeout elapses
void waitForIO(long timeout) void waitForIO(long timeout)
{ {
fd_set read_fd_set;
fd_set write_fd_set;
fd_set exc_fd_set;
int max_fd;
long select_timeout = -1;
struct timeval select_tv;
CURLMcode mres; CURLMcode mres;
FD_ZERO(&read_fd_set); #ifdef HAVE_CURL_MULTI_POLL
FD_ZERO(&write_fd_set); mres = curl_multi_poll(m_multi, nullptr, 0, timeout, nullptr);
FD_ZERO(&exc_fd_set);
mres = curl_multi_fdset(m_multi, &read_fd_set,
&write_fd_set, &exc_fd_set, &max_fd);
if (mres != CURLM_OK) { if (mres != CURLM_OK) {
errorstream<<"curl_multi_fdset" errorstream << "curl_multi_poll returned error code "
<<" returned error code "<<mres << mres << std::endl;
<<std::endl;
select_timeout = 0;
} }
#else
// If there's nothing to do curl_multi_wait() will immediately return
// so we have to emulate the sleeping.
mres = curl_multi_timeout(m_multi, &select_timeout); fd_set dummy;
int max_fd;
mres = curl_multi_fdset(m_multi, &dummy, &dummy, &dummy, &max_fd);
if (mres != CURLM_OK) { if (mres != CURLM_OK) {
errorstream<<"curl_multi_timeout" errorstream << "curl_multi_fdset returned error code "
<<" returned error code "<<mres << mres << std::endl;
<<std::endl; max_fd = -1;
select_timeout = 0;
} }
// Limit timeout so new requests get through if (max_fd == -1) { // curl has nothing to wait for
if (select_timeout < 0 || select_timeout > timeout) if (timeout > 0)
select_timeout = timeout; sleep_ms(timeout);
} else {
mres = curl_multi_wait(m_multi, nullptr, 0, timeout, nullptr);
if (select_timeout > 0) { if (mres != CURLM_OK) {
// in Winsock it is forbidden to pass three empty errorstream << "curl_multi_wait returned error code "
// fd_sets to select(), so in that case use sleep_ms << mres << std::endl;
if (max_fd != -1) {
select_tv.tv_sec = select_timeout / 1000;
select_tv.tv_usec = (select_timeout % 1000) * 1000;
int retval = select(max_fd + 1, &read_fd_set,
&write_fd_set, &exc_fd_set,
&select_tv);
if (retval == -1) {
#ifdef _WIN32
errorstream<<"select returned error code "
<<WSAGetLastError()<<std::endl;
#else
errorstream<<"select returned error code "
<<errno<<std::endl;
#endif
}
}
else {
sleep_ms(select_timeout);
} }
} }
#endif
} }
void *run() void *run()