cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: CURL loops infinitely when cable is pulled out.

From: Sonia Subramanian <sonia_subramanian_at_symantec.com>
Date: Sun, 22 Apr 2007 18:28:42 -0700

As requested the scenario where this failed:

The test scenario is as follows:

Start a download.
Pull the cable.
Start download again from the byte the prev download terminated.
Use CURL_RESUME_FROM option.
What I got back was an HTTP 416.

When I stepped thru the code I found the problem described below, the
range value was set correctly, but when it reached the http.c functions
the contents were invalid. I then tried to figure out where it got
deleted and it was in CURL disconnect. So all I did was reset the range
value after CURL-disconnect to be safe. I am not allowed to post
patches, but I hope this helps.

Thanks,
Sonia.

-----Original Message-----
From: Sonia Subramanian
Sent: Friday, April 20, 2007 5:53 PM
To: 'libcurl development'
Cc: Charlotte Chang; Robert Spath; Shalu Jain
Subject: RE: CURL loops infinitely when cable is pulled out.

Hi,

I tried this out with the new code and there are 2 issues I thought I
would bring up:

One issue with partial download that I fixed:
1)
This was when I tried to resume download of an already partially
downloaded file.

In the function createconnection in url.c

I had to add the following lines:

else {
       /*
        * This is a brand new connection, so let's store it in the
connection
        * cache of ours!
        */
-> //Fix ssubrama - we have probably called Curl Disconnect
-> //Reset the entire resume from structure - to be safe.

-> data->reqdata.resume_from = data->set.set_resume_from;
-> if (data->reqdata.resume_from) {
-> if (data->reqdata.rangestringalloc == TRUE)
-> free(data->reqdata.range);
-> data->reqdata.range = aprintf("%" FORMAT_OFF_T
"-",
-> data->reqdata.resume_from);
-> if(!data->reqdata.range)
-> return CURLE_OUT_OF_MEMORY;
->
-> /* tell ourselves to fetch this range */
-> data->reqdata.use_range = TRUE; /* enable
range download */
-> data->reqdata.rangestringalloc = TRUE; /* mark
range string allocated */
-> }
-> else if (data->set.set_range) {
-> /* There is a range, but is not a resume, useful
for random ftp access */
-> data->reqdata.range = strdup(data->set.set_range);
-> if(!data->reqdata.range)
-> return CURLE_OUT_OF_MEMORY;
-> data->reqdata.rangestringalloc = TRUE; /* mark
range string allocated */
-> data->reqdata.use_range = TRUE; /* enable
range download */
-> }
-> else
-> data->reqdata.use_range = FALSE; /* disable
range download */
-> ConnectionStore(data, conn);
     }
   
     /* Continue connectdata initialization here. */
   

Because in
    reuse = ConnectionExists(data, conn, &conn_temp); if we call
Curl_disconnect - the partial - resume from information always gets
freed and is never reinitialized. So here I am checking if allocated I
am freeing it and then copying again. After this fix it worked.

The other issue is that the infinite loop does not go away.
If select returns 0 Curl_readwrite is called again and no condition
there terminates the loop.
(transfer.c
Function

static CURLcode
Transfer(struct connectdata *conn)
{
.
.
.

switch (Curl_socket_ready(fd_read, fd_write, 1000)) {
    case -1: /* select() error, stop reading */
#ifdef EINTR
      /* The EINTR is not serious, and it seems you might get this more
         ofen when using the lib in a multi-threaded environment! */
      if(SOCKERRNO == EINTR)
        ;
      else
#endif
        done = TRUE; /* no more read or write */
      continue;
    case 0: /* timeout */
    default: /* readable descriptors */

      result = Curl_readwrite(conn, &done);
      break;
    }
    if(result)
      return result;

    /* "done" signals to us if the transfer(s) are ready */
  }

  return CURLE_OK;
}

I am not sure about other implications and don't want to change anything
without your input.
I would appreciate your comments on the same. Also if you think that the
code is behaving as it should but the problem lies in the return values,
I would appreciate your letting us know,

Thanks,
Sonia.

-----Original Message-----
From: Sonia Subramanian
Sent: Thursday, April 19, 2007 8:47 PM
To: 'libcurl development'
Cc: Charlotte Chang; Robert Spath; Shalu Jain
Subject: RE: CURL loops infinitely when cable is pulled out.

Hi,

Thanks. I will try this out with the new code.

Thanks,
Sonia.

-----Original Message-----
From: curl-library-bounces_at_cool.haxx.se
[mailto:curl-library-bounces_at_cool.haxx.se] On Behalf Of Daniel Stenberg
Sent: Thursday, April 19, 2007 1:08 PM
To: libcurl development
Cc: Charlotte Chang; Robert Spath; Shalu Jain
Subject: RE: CURL loops infinitely when cable is pulled out.

On Thu, 19 Apr 2007, Sonia Subramanian wrote:

> 1. We don't have poll() and we probably will use select.
> 2. On this platform select returns 0 as I verified with 7.15.4

You mean when select() times out? That's pretty normal.

> 3. In the code that calls it Curl_readwrite is a value of select_res
==0
> handled?

Yes of course. timeouts are very frequent on all platforms for slow or
stalled
transfers.

> Is a select_res value of 0 valid?

Yes, it means the socket didn't turn readable within the given time
(assuming
we talk about downloads).

-- 
  Commercial curl and libcurl Technical Support:
http://haxx.se/curl.html
Received on 2007-04-23