From 45c1741235a1fbd54484fa1c67ea68569dcfa23e Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:28 -0400 Subject: Refactor http.h USE_CURL_MULTI fill_active_slots(). This removes all of the boilerplate and http-internal stuff from fill_active_slots() and makes it easy to turn into a callback. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'http.c') diff --git a/http.c b/http.c index c6fb8ace9..1f305bd35 100644 --- a/http.c +++ b/http.c @@ -372,6 +372,7 @@ int start_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl); + int num_transfers; if (curlm_result != CURLM_OK && curlm_result != CURLM_CALL_MULTI_PERFORM) { @@ -379,11 +380,34 @@ int start_active_slot(struct active_request_slot *slot) slot->in_use = 0; return 0; } + + /* + * We know there must be something to do, since we just added + * something. + */ + curl_multi_perform(curlm, &num_transfers); #endif return 1; } #ifdef USE_CURL_MULTI +void fill_active_slots(void) +{ + struct active_request_slot *slot = active_queue_head; + + while (active_requests < max_requests) + if (!fill_active_slot()) + break; + + while (slot != NULL) { + if (!slot->in_use && slot->curl != NULL) { + curl_easy_cleanup(slot->curl); + slot->curl = NULL; + } + slot = slot->next; + } +} + void step_active_slots(void) { int num_transfers; -- cgit v1.2.1 From fc57b6aaa5bc59ecbe0c052b98196a93b35760a5 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:34 -0400 Subject: Make function to refill http queue a callback This eliminates the last function provided by the code using http.h as a global symbol, so it should be possible to have multiple programs using http.h in the same executable, and it also adds an argument to that callback, so that info can be passed into the callback without being global. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'http.c') diff --git a/http.c b/http.c index 1f305bd35..a95483be8 100644 --- a/http.c +++ b/http.c @@ -391,13 +391,39 @@ int start_active_slot(struct active_request_slot *slot) } #ifdef USE_CURL_MULTI +struct fill_chain { + void *data; + int (*fill)(void *); + struct fill_chain *next; +}; + +static struct fill_chain *fill_cfg = NULL; + +void add_fill_function(void *data, int (*fill)(void *)) +{ + struct fill_chain *new = malloc(sizeof(*new)); + struct fill_chain **linkp = &fill_cfg; + new->data = data; + new->fill = fill; + new->next = NULL; + while (*linkp) + linkp = &(*linkp)->next; + *linkp = new; +} + void fill_active_slots(void) { struct active_request_slot *slot = active_queue_head; - while (active_requests < max_requests) - if (!fill_active_slot()) + while (active_requests < max_requests) { + struct fill_chain *fill; + for (fill = fill_cfg; fill; fill = fill->next) + if (fill->fill(fill->data)) + break; + + if (!fill) break; + } while (slot != NULL) { if (!slot->in_use && slot->curl != NULL) { -- cgit v1.2.1 From 3278cd0a39c30c6c3082fc5feed0f9bd98b5f628 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:00 -0400 Subject: Properly cleanup in http_cleanup so builtin-fetch does not segfault Junio and I both noticed that the new builtin-fetch was segfaulting immediately on http/https/ftp style URLs (those that went through libcurl and the commit walker). Although the builtin-fetch changes in this area were really just minor refactorings there was one major change made: we invoked http_init(), http_cleanup() then http_init() again in the same process. When we call curl_easy_cleanup() on each active_request_slot we are telling libcurl we did not want that buffer to be used again. Unfortunately we did not also deallocate the active_request_slot itself nor did we NULL out active_queue_head. This lead us to attempt to reuse these cleaned up libcurl handles when we later tried to invoke http_init() a second time to reactivate the curl library. The next file get operation then immediately segfaulted on most versions of libcurl. Properly freeing our own buffers and clearing the list causes us to reinitialize the curl buffers again if/when we need to use libcurl from within this same process. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'http.c') diff --git a/http.c b/http.c index a95483be8..87ebf7b86 100644 --- a/http.c +++ b/http.c @@ -276,6 +276,7 @@ void http_cleanup(void) #endif while (slot != NULL) { + struct active_request_slot *next = slot->next; #ifdef USE_CURL_MULTI if (slot->in_use) { curl_easy_getinfo(slot->curl, @@ -287,8 +288,10 @@ void http_cleanup(void) #endif if (slot->curl != NULL) curl_easy_cleanup(slot->curl); - slot = slot->next; + free(slot); + slot = next; } + active_queue_head = NULL; #ifndef NO_CURL_EASY_DUPHANDLE curl_easy_cleanup(curl_default); @@ -300,7 +303,7 @@ void http_cleanup(void) curl_global_cleanup(); curl_slist_free_all(pragma_header); - pragma_header = NULL; + pragma_header = NULL; } struct active_request_slot *get_active_slot(void) -- cgit v1.2.1