On Thu, 28 Mar 2013, Sam Deane wrote:
I've eliminated GCD dispatch sources as a culprit I think, by writing an alternative version of the test which uses curl_multi_wait/curl_multi_perform, instead of curl_multi_socket_action plus callbacks.This one also exhibits the same crash:
1. You didn't eliminate gcd completely. I had to remove a bunch of more uses. 2. You extracted a URL with CURLINFO_EFFECTIVE_URL and then you freed the handle before you used the data so you deferred already freed memory. 3. You freed the list you extracted with CURLINFO_PRIVATE _before_ you cleaned up the handle and thus caused another deferring of freed memory. See attached source that has these flaws fixed. Works fine for me. -- / daniel.haxx.se
/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2013, Daniel Stenberg, <[email protected]>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ***************************************************************************/ /* Example application code using the multi socket interface to download multiple files at once, but instead of using curl_multi_perform and curl_multi_wait, which uses select(), we use gcd. */ #include <stdio.h> #include <stdlib.h> #include <curl/curl.h> #include <string.h> #define log_message(...) fprintf(stderr, __VA_ARGS__) #define log_error(...) fprintf(stderr, "ERROR: " __VA_ARGS__) void add_download(const char *url); int remaining = 0; int repeats = 20; CURLM *curl_handle; void curl_perform_wait() { long timeout_ms = -1; CURLMcode result = curl_multi_timeout(curl_handle, &timeout_ms); if (result != CURLM_OK) log_error("curl_multi_timeout error %d", result); if (timeout_ms < 1) timeout_ms = 1; int numfds = 0; result = curl_multi_wait(curl_handle, NULL, 0, (int)timeout_ms, &numfds); if (result != CURLM_OK) log_error("curl_multi_wait error %d", result); int numrunning = 0; result = curl_multi_perform(curl_handle, &numrunning); if (result != CURLM_OK) log_error("curl_multi_perform error %d", result); int pending = 0; CURLMsg *message; while ((message = curl_multi_info_read(curl_handle, &pending))) { switch (message->msg) { case CURLMSG_DONE: { const char* done_url; CURL* easy = message->easy_handle; curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &done_url); CURLcode code = message->data.result; printf("%s DONE\ncode:%d - %s\n", done_url, code, curl_easy_strerror(code)); struct curl_slist* list; curl_easy_getinfo(easy, CURLINFO_PRIVATE, &list); --remaining; if (--repeats) { add_download(done_url); } curl_multi_remove_handle(curl_handle, easy); curl_easy_cleanup(easy); curl_slist_free_all(list); break; } default: log_error("CURLMSG default\n"); abort(); } } if (remaining == 0) { curl_multi_cleanup(curl_handle); exit(0); } } int debug_func(CURL *curl, curl_infotype infoType, char *info, size_t infoLength, void *userp) { char* string = strndup(info, infoLength); fprintf(stderr, "debug %d: %s", infoType, string); free(string); return 0; } void add_download(const char *url) { CURL *handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_URL, url); curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, debug_func); curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); curl_easy_setopt(handle, CURLOPT_URL, url); char randomname[CURL_ERROR_SIZE]; char makecmd[CURL_ERROR_SIZE]; char chmodcmd[CURL_ERROR_SIZE]; char delcmd[CURL_ERROR_SIZE]; sprintf(randomname, "test-%d", rand()); sprintf(makecmd, "*MKD %s", randomname); sprintf(chmodcmd, "SITE CHMOD 0744 %s", randomname); sprintf(delcmd, "DELE %s", randomname); struct curl_slist* list = curl_slist_append(NULL, makecmd); list = curl_slist_append(list, chmodcmd); list = curl_slist_append(list, "*DELE file1.txt"); list = curl_slist_append(list, "*DELE file2.txt"); list = curl_slist_append(list, delcmd); curl_easy_setopt(handle, CURLOPT_PRIVATE, list); #if 0 curl_easy_setopt(handle, CURLOPT_POSTQUOTE, list); #endif long timeout = 60; curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, timeout); curl_easy_setopt(handle, CURLOPT_NOBODY, 1); ++remaining; curl_multi_add_handle(curl_handle, handle); log_message("Added download %s\n", url); } int main(int argc, char **argv) { int numrunning = 1; if (argc <= 1) return 0; if (curl_global_init(CURL_GLOBAL_ALL)) { log_error("Could not init cURL\n"); return 1; } curl_handle = curl_multi_init(); while (argc-- > 1) { add_download(argv[argc]); } while(1) curl_perform_wait(); return 0; }
------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
