{"thread":{"id":"3624","subject":"[PATCH 2/6] HTTP slot reuse fixes","startedAt":"2006-03-11T04:18:01Z","lastAt":"2006-03-11T04:18:01Z","messageCount":1,"participants":["Nick Hengeveld"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"17445","messageId":"20060311041801.GD3997@reactrix.com","threadId":"3624","inReplyTo":null,"subject":"[PATCH 2/6] HTTP slot reuse fixes","fromName":"Nick Hengeveld","fromEmail":"nickh@reactrix.com","sentAt":"2006-03-11T04:18:01Z","receivedAt":"2006-03-11T04:18:01Z","isPatch":true,"sender":{"key":"nickh@reactrix.com","avatar":null},"body":"Incorporate into http-push a fix related to accessing slot results after\nthe slot was reused, and fix a case in run_active_slot where a\nfinished slot wasn't detected if the slot was reused.\n\n---\n\n http-push.c |   56 +++++++++++++++++++++++++++++++++++++++-----------------\n http.c      |    8 +++++++-\n http.h      |    1 +\n 3 files changed, 47 insertions(+), 18 deletions(-)\n\n097851a0a1d713a9b69eb700b37809734af0c31e\ndiff --git a/http-push.c b/http-push.c\nindex 4c1b0c3..1b0b3a8 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -302,6 +302,7 @@ static void start_move(struct transfer_r\n static int refresh_lock(struct remote_lock *check_lock)\n {\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tchar *if_header;\n \tchar timeout_header[25];\n \tstruct curl_slist *dav_headers = NULL;\n@@ -329,6 +330,7 @@ static int refresh_lock(struct remote_lo\n \t\tdav_headers = curl_slist_append(dav_headers, timeout_header);\n \n \t\tslot = get_active_slot();\n+\t\tslot->results = &results;\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);\n@@ -337,8 +339,8 @@ static int refresh_lock(struct remote_lo\n \n \t\tif (start_active_slot(slot)) {\n \t\t\trun_active_slot(slot);\n-\t\t\tif (slot->curl_result != CURLE_OK) {\n-\t\t\t\tfprintf(stderr, \"Got HTTP error %ld\\n\", slot->http_code);\n+\t\t\tif (results.curl_result != CURLE_OK) {\n+\t\t\t\tfprintf(stderr, \"Got HTTP error %ld\\n\", results.http_code);\n \t\t\t\tlock->active = 0;\n \t\t\t} else {\n \t\t\t\tlock->active = 1;\n@@ -509,16 +511,18 @@ static int fetch_index(unsigned char *sh\n \n \tFILE *indexfile;\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \n \t/* Don't use the index if the pack isn't there */\n \turl = xmalloc(strlen(remote->url) + 65);\n \tsprintf(url, \"%s/objects/pack/pack-%s.pack\", remote->url, hex);\n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n \tcurl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);\n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result != CURLE_OK) {\n+\t\tif (results.curl_result != CURLE_OK) {\n \t\t\tfree(url);\n \t\t\treturn error(\"Unable to verify pack %s is available\",\n \t\t\t\t     hex);\n@@ -543,6 +547,7 @@ static int fetch_index(unsigned char *sh\n \t\t\t     filename);\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);\n \tcurl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);\n@@ -566,7 +571,7 @@ static int fetch_index(unsigned char *sh\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result != CURLE_OK) {\n+\t\tif (results.curl_result != CURLE_OK) {\n \t\t\tfree(url);\n \t\t\tfclose(indexfile);\n \t\t\treturn error(\"Unable to get pack index %s\\n%s\", url,\n@@ -606,6 +611,7 @@ static int fetch_indices(void)\n \tint i = 0;\n \n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \n \tdata = xmalloc(4096);\n \tmemset(data, 0, 4096);\n@@ -620,16 +626,17 @@ static int fetch_indices(void)\n \tsprintf(url, \"%s/objects/info/packs\", remote->url);\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);\n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result != CURLE_OK) {\n+\t\tif (results.curl_result != CURLE_OK) {\n \t\t\tfree(buffer.buffer);\n \t\t\tfree(url);\n-\t\t\tif (slot->http_code == 404)\n+\t\t\tif (results.http_code == 404)\n \t\t\t\treturn 0;\n \t\t\telse\n \t\t\t\treturn error(\"%s\", curl_errorstr);\n@@ -716,6 +723,7 @@ int fetch_ref(char *ref, unsigned char *\n         struct buffer buffer;\n \tchar *base = remote->url;\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n         buffer.size = 41;\n         buffer.posn = 0;\n         buffer.buffer = hex;\n@@ -723,13 +731,14 @@ int fetch_ref(char *ref, unsigned char *\n         \n \turl = quote_ref_url(base, ref);\n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);\n \tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result != CURLE_OK)\n+\t\tif (results.curl_result != CURLE_OK)\n \t\t\treturn error(\"Couldn't get %s for %s\\n%s\",\n \t\t\t\t     url, ref, curl_errorstr);\n \t} else {\n@@ -913,6 +922,7 @@ xml_cdata(void *userData, const XML_Char\n static struct remote_lock *lock_remote(char *path, long timeout)\n {\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tstruct buffer out_buffer;\n \tstruct buffer in_buffer;\n \tchar *out_data;\n@@ -946,14 +956,15 @@ static struct remote_lock *lock_remote(c\n \twhile (ep) {\n \t\t*ep = 0;\n \t\tslot = get_active_slot();\n+\t\tslot->results = &results;\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);\n \t\tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);\n \t\tif (start_active_slot(slot)) {\n \t\t\trun_active_slot(slot);\n-\t\t\tif (slot->curl_result != CURLE_OK &&\n-\t\t\t    slot->http_code != 405) {\n+\t\t\tif (results.curl_result != CURLE_OK &&\n+\t\t\t    results.http_code != 405) {\n \t\t\t\tfprintf(stderr,\n \t\t\t\t\t\"Unable to create branch path %s\\n\",\n \t\t\t\t\turl);\n@@ -985,6 +996,7 @@ static struct remote_lock *lock_remote(c\n \tdav_headers = curl_slist_append(dav_headers, \"Content-Type: text/xml\");\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);\n \tcurl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);\n@@ -1003,7 +1015,7 @@ static struct remote_lock *lock_remote(c\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result == CURLE_OK) {\n+\t\tif (results.curl_result == CURLE_OK) {\n \t\t\tctx.name = xcalloc(10, 1);\n \t\t\tctx.len = 0;\n \t\t\tctx.cdata = NULL;\n@@ -1053,6 +1065,7 @@ static struct remote_lock *lock_remote(c\n static int unlock_remote(struct remote_lock *lock)\n {\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tchar *lock_token_header;\n \tstruct curl_slist *dav_headers = NULL;\n \tint rc = 0;\n@@ -1063,6 +1076,7 @@ static int unlock_remote(struct remote_l\n \tdav_headers = curl_slist_append(dav_headers, lock_token_header);\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);\n \tcurl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);\n \tcurl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);\n@@ -1070,11 +1084,11 @@ static int unlock_remote(struct remote_l\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result == CURLE_OK)\n+\t\tif (results.curl_result == CURLE_OK)\n \t\t\trc = 1;\n \t\telse\n \t\t\tfprintf(stderr, \"Got HTTP error %ld\\n\",\n-\t\t\t\tslot->http_code);\n+\t\t\t\tresults.http_code);\n \t} else {\n \t\tfprintf(stderr, \"Unable to start request\\n\");\n \t}\n@@ -1091,6 +1105,7 @@ static void crawl_remote_refs(char *path\n {\n \tchar *url;\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tstruct buffer in_buffer;\n \tstruct buffer out_buffer;\n \tchar *in_data;\n@@ -1125,6 +1140,7 @@ static void crawl_remote_refs(char *path\n \tdav_headers = curl_slist_append(dav_headers, \"Content-Type: text/xml\");\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);\n \tcurl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);\n@@ -1137,7 +1153,7 @@ static void crawl_remote_refs(char *path\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result == CURLE_OK) {\n+\t\tif (results.curl_result == CURLE_OK) {\n \t\t\tctx.name = xcalloc(10, 1);\n \t\t\tctx.len = 0;\n \t\t\tctx.cdata = NULL;\n@@ -1171,6 +1187,7 @@ static void get_remote_object_list(unsig\n {\n \tchar *url;\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tstruct buffer in_buffer;\n \tstruct buffer out_buffer;\n \tchar *in_data;\n@@ -1203,6 +1220,7 @@ static void get_remote_object_list(unsig\n \tdav_headers = curl_slist_append(dav_headers, \"Content-Type: text/xml\");\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);\n \tcurl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);\n@@ -1215,7 +1233,7 @@ static void get_remote_object_list(unsig\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result == CURLE_OK) {\n+\t\tif (results.curl_result == CURLE_OK) {\n \t\t\tremote_dir_exists[parent] = 1;\n \t\t\tctx.name = xcalloc(10, 1);\n \t\t\tctx.len = 0;\n@@ -1250,6 +1268,7 @@ static void get_remote_object_list(unsig\n static int locking_available(void)\n {\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tstruct buffer in_buffer;\n \tstruct buffer out_buffer;\n \tchar *in_data;\n@@ -1278,6 +1297,7 @@ static int locking_available(void)\n \tdav_headers = curl_slist_append(dav_headers, \"Content-Type: text/xml\");\n \t\n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);\n \tcurl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);\n@@ -1290,7 +1310,7 @@ static int locking_available(void)\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n-\t\tif (slot->curl_result == CURLE_OK) {\n+\t\tif (results.curl_result == CURLE_OK) {\n \t\t\tctx.name = xcalloc(10, 1);\n \t\t\tctx.len = 0;\n \t\t\tctx.cdata = NULL;\n@@ -1416,6 +1436,7 @@ static void get_delta(struct rev_info *r\n static int update_remote(unsigned char *sha1, struct remote_lock *lock)\n {\n \tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n \tchar *out_data;\n \tchar *if_header;\n \tstruct buffer out_buffer;\n@@ -1437,6 +1458,7 @@ static int update_remote(unsigned char *\n \tout_buffer.buffer = out_data;\n \n \tslot = get_active_slot();\n+\tslot->results = &results;\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);\n \tcurl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);\n \tcurl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);\n@@ -1451,10 +1473,10 @@ static int update_remote(unsigned char *\n \t\trun_active_slot(slot);\n \t\tfree(out_data);\n \t\tfree(if_header);\n-\t\tif (slot->curl_result != CURLE_OK) {\n+\t\tif (results.curl_result != CURLE_OK) {\n \t\t\tfprintf(stderr,\n \t\t\t\t\"PUT error: curl result=%d, HTTP code=%ld\\n\",\n-\t\t\t\tslot->curl_result, slot->http_code);\n+\t\t\t\tresults.curl_result, results.http_code);\n \t\t\t/* We should attempt recovery? */\n \t\t\treturn 0;\n \t\t}\ndiff --git a/http.c b/http.c\nindex 14a7669..9604e33 100644\n--- a/http.c\n+++ b/http.c\n@@ -339,6 +339,7 @@ struct active_request_slot *get_active_s\n \tslot->in_use = 1;\n \tslot->local = NULL;\n \tslot->results = NULL;\n+\tslot->finished = NULL;\n \tslot->callback_data = NULL;\n \tslot->callback_func = NULL;\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);\n@@ -389,8 +390,10 @@ void run_active_slot(struct active_reque\n \tfd_set excfds;\n \tint max_fd;\n \tstruct timeval select_timeout;\n+\tint finished = 0;\n \n-\twhile (slot->in_use) {\n+\tslot->finished = &finished;\n+\twhile (!finished) {\n \t\tdata_received = 0;\n \t\tstep_active_slots();\n \n@@ -442,6 +445,9 @@ static void finish_active_slot(struct ac\n \tclosedown_active_slot(slot);\n         curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);\n \n+\tif (slot->finished != NULL)\n+\t\t(*slot->finished) = 1;\n+\n \t/* Store slot results so they can be read after the slot is reused */\n \tif (slot->results != NULL) {\n \t\tslot->results->curl_result = slot->curl_result;\ndiff --git a/http.h b/http.h\nindex 36fa154..9ca16ac 100644\n--- a/http.h\n+++ b/http.h\n@@ -35,6 +35,7 @@ struct active_request_slot\n \tint in_use;\n \tCURLcode curl_result;\n \tlong http_code;\n+\tint *finished;\n \tstruct slot_results *results;\n \tvoid *callback_data;\n \tvoid (*callback_func)(void *data);\n-- \n1.2.4.g8e81-dirty\n"}]}