Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/gnuwin32/embeddedR.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ void Rf_endEmbeddedR(int fatal)
{
R_RunExitFinalizers();
CleanEd();
CurlCleanup();
R_CleanTempDir();
if(!fatal){
Rf_KillAllDevices();
Expand Down
1 change: 1 addition & 0 deletions src/gnuwin32/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ static void Rstd_CleanUp(SA_TYPE saveact, int status, int runLast)
CleanEd();
KillAllDevices(); /* Unix does not do this under SA_SUICIDE */
AllDevicesKilled = TRUE; /* used in devWindows.c to inhibit callbacks */
CurlCleanup();
R_CleanTempDir(); /* changes directory */
if (R_Interactive && CharacterMode == RTerm)
SetConsoleTitle(oldtitle);
Expand Down
1 change: 1 addition & 0 deletions src/include/Defn.h
Original file line number Diff line number Diff line change
Expand Up @@ -2294,6 +2294,7 @@ SEXP fixup_NaRm(SEXP args); /* summary.c */
void invalidate_cached_recodings(void); /* from sysutils.c */
void resetICUcollator(Rboolean disable); /* from util.c */
void dt_invalidate_locale(void); /* from Rstrptime.h */
extern void CurlCleanup(void); /* from internet.c */
extern int R_OutputCon; /* from connections.c */
extern int R_InitReadItemDepth, R_ReadItemDepth; /* from serialize.c */
void get_current_mem(size_t *,size_t *,size_t *); /* from memory.c */
Expand Down
2 changes: 2 additions & 0 deletions src/include/Rmodules/Rinternet.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef int (*R_HTTPDCreateRoutine)(const char *ip, int port);
typedef void (*R_HTTPDStopRoutine)(void);

typedef SEXP (*R_CurlRoutine)(SEXP call, SEXP op, SEXP args, SEXP rho);
typedef void (*R_CurlCleanupRoutine)(void);

typedef struct {
R_DownloadRoutine download;
Expand All @@ -67,6 +68,7 @@ typedef struct {
R_CurlRoutine curlVersion;
R_CurlRoutine curlGetHeaders;
R_CurlRoutine curlDownload;
R_CurlCleanupRoutine curlCleanup;
R_NewUrlRoutine newcurlurl;
} R_InternetRoutines;

Expand Down
9 changes: 9 additions & 0 deletions src/main/internet.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,15 @@ attribute_hidden SEXP do_curlDownload(SEXP call, SEXP op, SEXP args, SEXP rho)
}
}

void CurlCleanup(void)
{
if(!initialized) internet_Init();
if(initialized > 0)
(*ptr->curlCleanup)();
else
error(_("internet routines cannot be loaded"));
}

Rconnection attribute_hidden
R_newCurlUrl(const char *description, const char * const mode, SEXP headers, int type)
{
Expand Down
2 changes: 2 additions & 0 deletions src/modules/internet/internet.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef int_fast64_t DLsize_t; // used for download lengths and sizes
SEXP in_do_curlVersion(SEXP call, SEXP op, SEXP args, SEXP rho);
SEXP in_do_curlGetHeaders(SEXP call, SEXP op, SEXP args, SEXP rho);
SEXP in_do_curlDownload(SEXP call, SEXP op, SEXP args, SEXP rho);
void in_curlCleanup(void);
Rconnection
in_newCurlUrl(const char *description, const char * const mode, SEXP headers, int type);

Expand Down Expand Up @@ -729,6 +730,7 @@ R_init_internet(DllInfo *info)
tmp->curlVersion = in_do_curlVersion;
tmp->curlGetHeaders = in_do_curlGetHeaders;
tmp->curlDownload = in_do_curlDownload;
tmp->curlCleanup = in_curlCleanup;
tmp->newcurlurl = in_newCurlUrl;

R_setInternetRoutines(tmp);
Expand Down
25 changes: 21 additions & 4 deletions src/modules/internet/libcurl.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,31 @@ extern void Rsleep(double timeint);

static int current_timeout = 0;

// The multi-handle is shared between downloads for reusing connections
static CURLM *shared_mhnd = NULL;

static CURLM attribute_hidden *get_mhnd(void)
{
if(!shared_mhnd)
shared_mhnd = curl_multi_init();
return shared_mhnd;
}

void attribute_hidden in_curlCleanup(void)
{
if(shared_mhnd){
curl_multi_cleanup(shared_mhnd);
shared_mhnd = NULL;
}
curl_global_cleanup();
}

# if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 28)

// curl/curl.h includes <sys/select.h> and headers it requires.

#define curl_multi_wait R_curl_multi_wait


static CURLMcode
R_curl_multi_wait(CURLM *multi_handle,
/* IGNORED */ void *unused,
Expand Down Expand Up @@ -565,8 +583,6 @@ static void download_cleanup(void *data)
if (c->hnd && c->hnd[i])
curl_easy_cleanup(c->hnd[i]);
}
if (c->mhnd)
curl_multi_cleanup(c->mhnd);
if (c->headers)
curl_slist_free_all(c->headers);

Expand Down Expand Up @@ -668,7 +684,8 @@ in_do_curlDownload(SEXP call, SEXP op, SEXP args, SEXP rho)
c.headers = headers = tmp;
}

CURLM *mhnd = curl_multi_init();
CURLM *mhnd = get_mhnd();

if (!mhnd)
error(_("could not create curl handle"));
c.mhnd = mhnd;
Expand Down
1 change: 1 addition & 0 deletions src/unix/Rembedded.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void Rf_endEmbeddedR(int fatal)
R_RunExitFinalizers();
CleanEd();
if(!fatal) KillAllDevices();
CurlCleanup();
R_CleanTempDir();
if(!fatal && R_CollectWarnings)
PrintWarnings(); /* from device close and .Last */
Expand Down
1 change: 1 addition & 0 deletions src/unix/sys-std.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ void Rstd_CleanUp(SA_TYPE saveact, int status, int runLast)
R_RunExitFinalizers();
CleanEd();
if(saveact != SA_SUICIDE) KillAllDevices();
CurlCleanup();
R_CleanTempDir();
if(saveact != SA_SUICIDE && R_CollectWarnings)
PrintWarnings(); /* from device close and (if run) .Last */
Expand Down