Skip to content

Commit 416e03f

Browse files
authored
Be more careful cleaning up after failed curl (#3996)
If there are curl failures, we need to remove the lock file etc, not just return. This PR captures all failures and forces via a goto statement to always deal with cleanup.
1 parent 94fe45d commit 416e03f

File tree

1 file changed

+32
-26
lines changed

1 file changed

+32
-26
lines changed

src/gmt_remote.c

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,8 @@ GMT_LOCAL size_t gmtremote_skip_large_files (struct GMT_CTRL *GMT, char * URL, s
520520
#define GMT_HASH_TIME_OUT 10L /* Not waiting longer than this to time out on getting the hash file */
521521

522522
GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL *GMT, char *url, char *file, char *orig, unsigned int index) {
523-
bool query = gmt_M_file_is_query (url);
524-
int curl_err = 0;
523+
bool query = gmt_M_file_is_query (url), turn_off = false;
524+
int curl_err = 0, error = 0;
525525
long time_spent;
526526
char *Lfile = NULL;
527527
FILE *fp = NULL;
@@ -534,48 +534,49 @@ GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL *GMT, char *url, char *file, ch
534534
Lfile = gmtremote_lockfile (API, file);
535535
if ((fp = fopen (Lfile, "w")) == NULL) {
536536
GMT_Report (API, GMT_MSG_ERROR, "Failed to create lock file %s\n", Lfile);
537+
gmt_M_str_free (Lfile);
537538
return 1;
538539
}
539540
gmtlib_file_lock (GMT, fileno(fp)); /* Attempt exclusive lock */
540541
}
541542

542543
if ((Curl = curl_easy_init ()) == NULL) {
543544
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to initiate curl - cannot obtain %s\n", url);
544-
return 1;
545+
error = 1; goto unlocking1;
545546
}
546547
if (curl_easy_setopt (Curl, CURLOPT_SSL_VERIFYPEER, 0L)) { /* Tell libcurl to not verify the peer */
547548
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to not verify the peer\n");
548-
return 1;
549+
error = 1; goto unlocking1;
549550
}
550551
if (curl_easy_setopt (Curl, CURLOPT_FOLLOWLOCATION, 1L)) { /* Tell libcurl to follow 30x redirects */
551552
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to follow redirects\n");
552-
return 1;
553+
error = 1; goto unlocking1;
553554
}
554555
if (curl_easy_setopt (Curl, CURLOPT_FAILONERROR, 1L)) { /* Tell libcurl to fail on 4xx responses (e.g. 404) */
555556
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to fail for 4xx responses\n");
556-
return 1;
557+
error = 1; goto unlocking1;
557558
}
558559
if (curl_easy_setopt (Curl, CURLOPT_URL, url)) { /* Set the URL to copy */
559560
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to read from %s\n", url);
560-
return 1;
561+
error = 1; goto unlocking1;
561562
}
562563
if (curl_easy_setopt (Curl, CURLOPT_TIMEOUT, GMT_HASH_TIME_OUT)) { /* Set a max timeout */
563564
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to time out after %ld seconds\n", GMT_HASH_TIME_OUT);
564-
return 1;
565+
error = 1; goto unlocking1;
565566
}
566567
urlfile.filename = file; /* Set pointer to local filename */
567568
/* Define our callback to get called when there's data to be written */
568569
if (curl_easy_setopt (Curl, CURLOPT_WRITEFUNCTION, gmtremote_fwrite_callback)) {
569570
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl output callback function\n");
570-
return 1;
571+
error = 1; goto unlocking1;
571572
}
572573
/* Set a pointer to our struct to pass to the callback */
573574
if (curl_easy_setopt (Curl, CURLOPT_WRITEDATA, &urlfile)) {
574575
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Failed to set curl option to write to %s\n", file);
575-
return 1;
576+
error = 1; goto unlocking1;
576577
}
577578
GMT_Report (GMT->parent, GMT_MSG_INFORMATION, "Downloading file %s ...\n", url);
578-
gmtremote_turn_on_ctrl_C_check (file);
579+
gmtremote_turn_on_ctrl_C_check (file); turn_off = true;
579580
begin = time (NULL);
580581
if ((curl_err = curl_easy_perform (Curl))) { /* Failed, give error message */
581582
end = time (NULL);
@@ -598,21 +599,23 @@ GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL *GMT, char *url, char *file, ch
598599
GMT->current.io.refreshed[index] = GMT->current.io.internet_error = true;
599600
}
600601
}
601-
return 1;
602+
error = 1; goto unlocking1;
602603
}
603604
curl_easy_cleanup (Curl);
604605
if (urlfile.fp) /* close the local file */
605606
fclose (urlfile.fp);
606607

608+
unlocking1:
609+
607610
if (!query) { /* Remove lock file after successful download */
608611
gmtlib_file_unlock (GMT, fileno(fp));
609612
fclose(fp);
610613
gmt_remove_file (GMT, Lfile);
611614
gmt_M_str_free (Lfile);
612615
}
613616

614-
gmtremote_turn_off_ctrl_C_check ();
615-
return 0;
617+
if (turn_off) gmtremote_turn_off_ctrl_C_check ();
618+
return error;
616619
}
617620

618621
GMT_LOCAL struct GMT_DATA_HASH *gmtremote_hash_load (struct GMT_CTRL *GMT, char *file, int *n) {
@@ -1111,8 +1114,8 @@ int gmtlib_file_is_jpeg2000_tile (struct GMTAPI_CTRL *API, char *file) {
11111114
}
11121115

11131116
int gmt_download_file (struct GMT_CTRL *GMT, const char *name, char *url, char *localfile, bool be_fussy) {
1114-
bool query = gmt_M_file_is_query (url);
1115-
int curl_err, error;
1117+
bool query = gmt_M_file_is_query (url), turn_off = false;
1118+
int curl_err, error = 0;
11161119
size_t fsize;
11171120
char *Lfile = NULL;
11181121
CURL *Curl = NULL;
@@ -1141,47 +1144,48 @@ int gmt_download_file (struct GMT_CTRL *GMT, const char *name, char *url, char *
11411144
Lfile = gmtremote_lockfile (API, (char *)name);
11421145
if ((fp = fopen (Lfile, "w")) == NULL) {
11431146
GMT_Report (API, GMT_MSG_ERROR, "Failed to create lock file %s\n", Lfile);
1147+
gmt_M_str_free (Lfile);
11441148
return 1;
11451149
}
11461150
gmtlib_file_lock (GMT, fileno(fp)); /* Attempt exclusive lock */
11471151
}
11481152

11491153
if ((Curl = curl_easy_init ()) == NULL) {
11501154
GMT_Report (API, GMT_MSG_ERROR, "Failed to initiate curl\n");
1151-
return 1;
1155+
error = 1; goto unlocking2;
11521156
}
11531157
if (curl_easy_setopt (Curl, CURLOPT_SSL_VERIFYPEER, 0L)) { /* Tell libcurl to not verify the peer */
11541158
GMT_Report (API, GMT_MSG_ERROR, "Failed to set curl option to not verify the peer\n");
1155-
return 1;
1159+
error = 1; goto unlocking2;
11561160
}
11571161
if (curl_easy_setopt (Curl, CURLOPT_FOLLOWLOCATION, 1L)) { /* Tell libcurl to follow 30x redirects */
11581162
GMT_Report (API, GMT_MSG_ERROR, "Failed to set curl option to follow redirects\n");
1159-
return 1;
1163+
error = 1; goto unlocking2;
11601164
}
11611165
if (curl_easy_setopt (Curl, CURLOPT_FAILONERROR, 1L)) { /* Tell libcurl to fail on 4xx responses (e.g. 404) */
1162-
return 1;
1166+
error = 1; goto unlocking2;
11631167
}
11641168

11651169
if (curl_easy_setopt (Curl, CURLOPT_URL, url)) { /* Set the URL to copy */
11661170
GMT_Report (API, GMT_MSG_ERROR, "Failed to set curl option to read from %s\n", url);
1167-
return 1;
1171+
error = 1; goto unlocking2;
11681172
}
11691173
urlfile.filename = localfile; /* Set pointer to local filename */
11701174
/* Define our callback to get called when there's data to be written */
11711175
if (curl_easy_setopt (Curl, CURLOPT_WRITEFUNCTION, gmtremote_fwrite_callback)) {
11721176
GMT_Report (API, GMT_MSG_ERROR, "Failed to set curl output callback function\n");
1173-
return 1;
1177+
error = 1; goto unlocking2;
11741178
}
11751179
/* Set a pointer to our struct to pass to the callback */
11761180
if (curl_easy_setopt (Curl, CURLOPT_WRITEDATA, &urlfile)) {
11771181
GMT_Report (API, GMT_MSG_ERROR, "Failed to set curl option to write to %s\n", localfile);
1178-
return 1;
1182+
error = 1; goto unlocking2;
11791183
}
11801184

11811185
gmtremote_find_and_give_data_attribution (API, name);
11821186

11831187
GMT_Report (API, GMT_MSG_INFORMATION, "Downloading file %s ...\n", url);
1184-
gmtremote_turn_on_ctrl_C_check (localfile);
1188+
gmtremote_turn_on_ctrl_C_check (localfile); turn_off = true;
11851189
if ((curl_err = curl_easy_perform (Curl))) { /* Failed, give error message */
11861190
if (be_fussy || !(curl_err == CURLE_REMOTE_FILE_NOT_FOUND || curl_err == CURLE_HTTP_RETURNED_ERROR)) { /* Unexpected failure - want to bitch about it */
11871191
GMT_Report (API, GMT_MSG_ERROR, "Libcurl Error: %s\n", curl_easy_strerror (curl_err));
@@ -1200,16 +1204,18 @@ int gmt_download_file (struct GMT_CTRL *GMT, const char *name, char *url, char *
12001204
if (urlfile.fp) /* close the local file */
12011205
fclose (urlfile.fp);
12021206

1207+
unlocking2:
1208+
12031209
if (!query) { /* Remove lock file after successful download */
12041210
gmtlib_file_unlock (GMT, fileno(fp));
12051211
fclose(fp);
12061212
gmt_remove_file (GMT, Lfile);
12071213
gmt_M_str_free (Lfile);
12081214
}
12091215

1210-
gmtremote_turn_off_ctrl_C_check ();
1216+
if (turn_off) gmtremote_turn_off_ctrl_C_check ();
12111217

1212-
error = gmtremote_convert_jp2_to_nc (API, localfile);
1218+
if (error == 0) error = gmtremote_convert_jp2_to_nc (API, localfile);
12131219

12141220
return (error);
12151221
}

0 commit comments

Comments
 (0)