cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: libcurl win32 multi-thread problem

From: Dan Fandrich <dan_at_coneharvesters.com>
Date: Tue, 19 Sep 2006 10:35:30 -0700

On Tue, Sep 19, 2006 at 05:30:09PM +0300, Razvan wrote:
> Hello people !
>
> I have an multi threaded application that must upload from each thread a file
> to an ftp server.
> The problem is that only one thread is uploading and the speed never reaches
> 60kb/s in the same LAN.

I'm not positive I know the source of this particular problem, but the source
code is full of errors. I'm assuming you're already doing the right thing
to build and link with a thread-safe C library.

> here is the function called from each thread:
>
>
>
> int ftp_upload(char* username, char* password, char* address, char* remote_dir,
> char* local_file, char* upload_as )
> {
> FILE * hd_src ;
> CURL* curl_handler;
> CURLcode res;
> char* REMOTE_URL;
> int hd ;
> struct stat file_info;
>
> char* buf_1; //[] = "RNFR " UPLOAD_FILE_AS;
> char* buf_2; //[] = "RNTO " RENAME_FILE_TO;
>
> curl_global_init(CURL_GLOBAL_ALL);

curl_global_init must *not* be called once from each thread--it's not thread
safe.

> curl_handler = curl_easy_init();
> curl_easy_setopt(curl_handler, CURLOPT_NOSIGNAL, TRUE) ;
>
> hd = open(local_file, O_RDONLY) ;
> fstat(hd, &file_info);
> close(hd) ;

It's unnecessary to open and close the file here. Just use stat instead
of fstat. Or use fstat(fileno(hd_src), &file_info) after the fopen in
the next line.

>
> hd_src = fopen(local_file, "rb");

You're not checking the return code from this function.

>
> buf_1=(char*)malloc(strlen("RNFR .temp")+strlen(upload_as));

This buffer is too small by one. The sprintf will overflow the buffer.

> buf_2=(char*)malloc(strlen(upload_as)+10);
> sprintf(buf_1,"RNFR %s.temp",upload_as);
> sprintf(buf_2,"RNTO %s.xxx",upload_as);
> curl_easy_setopt(curl_handler, CURLOPT_UPLOAD, TRUE) ;
>
> REMOTE_URL=(char*)malloc(strlen(username)+strlen(password)+strlen(address)
> +strlen(remote_dir)+strlen(upload_as)+11);

This buffer is also at least 1 too small.

> sprintf(REMOTE_URL," ftp://%s:%s@%s/%s/
> %s",username,password,address,remote_dir,upload_as);

Why the space at the beginning of the URL?

> curl_easy_setopt(curl_handler,CURLOPT_URL, REMOTE_URL);
>
> curl_easy_setopt(curl_handler, CURLOPT_READDATA, hd_src);

Are you using libcurl as a DLL? If so then then you must heed the
documentation and you "MUST use a CURLOPT_READFUNCTION".

>
> curl_easy_setopt(curl_handler, CURLOPT_INFILESIZE_LARGE,(curl_off_t)
> file_info.st_size);
>
> res = curl_easy_perform(curl_handler);
> curl_easy_cleanup(curl_handler);
> curl_global_cleanup();

Also not thread safe. This might be your problem, in fact. If the first
thread to complete calls curl_global_cleanup(), it's going to stomp on all
the other threads.

>
> fclose(hd_src); /* close the local file */
>
> return res;
> }

You need to spend more time in the man pages.

>>> Dan

-- 
http://www.MoveAnnouncer.com              The web change of address service
          Let webmasters know that your web site has moved
Received on 2006-09-19