libcurl: Manchmal "unhandled exception" bei download



  • Hey!

    In seltenen Fällen bekomme ich eine unhandled exception, wenn ich mit libcurl etwas downloaden möchte.
    Hier der Code:

    int OnDownloadWrite(char* data, unsigned int size, unsigned int nmemb, std::string* buffer)
    {
    	int returnValue = 0;
    
    	if(buffer)
    	{
    		buffer->append(data, size * nmemb);
    		returnValue = size * nmemb;
    	}
    
    	return returnValue;
    }
    
    // main()
    
        string data1, data2;
    
    	void* easyDownloadHandles[2];
    
    	easyDownloadHandles[0] = curl_easy_init();
    	easyDownloadHandles[1] = curl_easy_init();
    
    	void* multiDownloadHandle = curl_multi_init();
    
    	curl_easy_setopt(easyDownloadHandles[0], CURLOPT_URL, "http://www.***.com/file.zip");
    	curl_easy_setopt(easyDownloadHandles[0], CURLOPT_WRITEFUNCTION, OnDownloadWrite);
    	curl_easy_setopt(easyDownloadHandles[0], CURLOPT_WRITEDATA, &data1);
    
    	curl_easy_setopt(easyDownloadHandles[1], CURLOPT_URL, "http://www.***.com/file2.zip");
    	curl_easy_setopt(easyDownloadHandles[1], CURLOPT_WRITEFUNCTION, OnDownloadWrite);
    	curl_easy_setopt(easyDownloadHandles[1], CURLOPT_WRITEDATA, &data2);
    
    	curl_multi_add_handle(multiDownloadHandle, easyDownloadHandles[0]);
    	curl_multi_add_handle(multiDownloadHandle, easyDownloadHandles[1]);
    
    	int running = true;
    
    	while(running)
    	{
    		while(curl_multi_perform(multiDownloadHandle, &running) == CURLM_CALL_MULTI_PERFORM);
    
    		timeval timeoutVal = { 8 };
    
    		fd_set readFileDescriptor;
    		fd_set writeFileDescriptor;
    		fd_set exceptionFileDescriptor;
    
    		FD_ZERO(&readFileDescriptor);
    		FD_ZERO(&writeFileDescriptor);
    		FD_ZERO(&exceptionFileDescriptor);
    
    		int maxFileDescriptors;
    
    		if(curl_multi_fdset(multiDownloadHandle, &readFileDescriptor, &writeFileDescriptor, &exceptionFileDescriptor, &maxFileDescriptors))
    			break;
    
    		if(maxFileDescriptors > -1)
    		{
    			int result = select(maxFileDescriptors + 1, &readFileDescriptor, &writeFileDescriptor, &exceptionFileDescriptor, &timeoutVal);
    
    			if(result == -1)
    				break;
    		}
    		else
    			Sleep(100);
    	}
    
    	curl_multi_cleanup(multiDownloadHandle);
    	curl_easy_cleanup(easyDownloadHandles[0]);
    	curl_easy_cleanup(easyDownloadHandles[1]);
    

    Was mache ich falsch? Es funktioniert meistens, aber manchmal nicht:

    http://www.bilder-hochladen.net/files/bq9q-5-jpg.html

    Danke!
    MfG



  • ^^lass es im debugger laufen. der hält an, wenn die exception auftritt.
    🙂



  • Hält an genau derselben Stelle mit:

    ptd 0x0054a388 _tiddata *
    _initaddr 0x00474b60 void *
    _initarg 0x00549b50 void *



  • Amboss der Rabiator schrieb:

    Hält an genau derselben Stelle mit:
    ptd 0x0054a388 _tiddata *
    _initaddr 0x00474b60 void *
    _initarg 0x00549b50 void *

    wo im quelltext iss'n das? du musst die stelle im source code finden, wo das passiert.
    🙂



  • Genau dort, wie man es auf dem Bild sieht.
    (Im file threadex.c)



  • Amboss der Rabiator schrieb:

    Genau dort, wie man es auf dem Bild sieht.
    (Im file threadex.c)

    ok, dann mach 'nen backtrace, also rückwärts steppen bis du in dem von dir geschriebenen code bist.
    🙂



  • Wie "backtrace" ich denn (VS 2008)?
    Ist es "Step Out" (Shift+F11)?

    Danke für deine Geduld.



  • Mist!
    Das Problem scheint bekannt zu sein.
    Deshalb hasse ich es, externe libs zu benutzen. 100.000 Funktionen aber beinahe unbrauchbar jetzt, der Glump...

    Workaround ist, maximal ein easy-handle zum mutli-handle hinzuzufügen, sprich maximal eine Datei gleichzeitig runterzuladen.
    (Das Problem liegt angeblich im gleichzeitigen internen host-resolve).

    Kennt ihr vllt. ne Alternative zu libcurl?

    🙄



  • Amboss der Rabiator schrieb:

    Kennt ihr vllt. ne Alternative zu libcurl?

    naja, direkt mit sockets. 'nen HTTP-request abschicken und die zurückkommenden daten einsammeln. ist eigentlich garnicht so schwer. beispiel (getestet unter VS 2005):

    #include <windows.h>
    #include <stdio.h>
    
    #pragma comment (lib, "ws2_32.lib")
    
    void bye (char *s)
    {
      printf ("abort due to error in: %s\n", s);
      exit(0);
    }
    
    int main()
    {
      WSADATA wsa;
      SOCKET sock;
      SOCKADDR_IN sin;
      char *req = "GET /cms/index.php HTTP/1.0\r\n\r\n";
    
      if (0 != WSAStartup (MAKEWORD(2,0), &wsa))
        bye ("WSAStartup");
    
      sock = socket (AF_INET, SOCK_STREAM, 0);
      if (sock == INVALID_SOCKET)
        bye ("socket");
    
      memset (&sin, 0, sizeof(sin));
      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = inet_addr ("87.106.19.147"); // www.c-plusplus.net
      sin.sin_port = htons(80);
      if (SOCKET_ERROR == connect (sock, (struct sockaddr*)&sin, sizeof(sin)))
        bye ("connect");
    
      if (SOCKET_ERROR == send (sock, req, (int)strlen(req), 0))
        bye ("send");
    
      // daten abholen und alles anzeigen
      for (;;)
      {
        char buff[1024];
        int s;
        int r = recv (sock, buff, sizeof(buff), 0);
        if (r == 0 || r == SOCKET_ERROR)  // verbindung vom server zugemacht oder abbruch?
          break;
        for (s=0; s<r; s++)
          putchar (buff[s]);
      }
      printf ("\n-- fertig ---\n");
    }
    

    🙂


Anmelden zum Antworten