cURL / Mailing Lists / curl-library / Single Mail

curl-library

CURL loops infinitely when cable is pulled out.

From: Sonia Subramanian <sonia_subramanian_at_symantec.com>
Date: Wed, 18 Apr 2007 13:42:00 -0700

Hi,

 

I found a situation where CURL gets stuck in an infinite loop.

I wanted to check with you on whether this is a problem with CURL or the
underlying environment.

 

I am in an environment where when the cable is pulled out CURL is
looping infinitely in the following lines of code:

 

In Transfer.c

 

In

 

static CURLcode

Transfer(struct connectdata *conn)

 

The code is at:

1.

      result = Curl_readwrite(conn, &done);

      break;

    }

    if(result)

      return result;

(result is Ok - it does not return).

 

It goes to :

2.

while (!done) {

    curl_socket_t fd_read;

    curl_socket_t fd_write;

    int interval_ms;

 

    interval_ms = 1 * 1000;

 

3. if(k->keepon & KEEP_READ)

      fd_read = conn->sockfd;

 

4.

if(k->keepon & KEEP_WRITE) it executes the else part

fd_write = CURL_SOCKET_BAD;

 

5. switch (Curl_select(fd_read, fd_write, interval_ms)) {

 

6. default: /* readable descriptors */

      result = Curl_readwrite(conn, &done);

Stepping into Curl_readwrite

 

 1. if(k->keepon & KEEP_READ)

    fd_read = conn->sockfd;

2. if(k->keepon & KEEP_WRITE) it executes the else part

fd_write = CURL_SOCKET_BAD;

3.

select_res = Curl_select(fd_read, fd_write, 0);

  if(select_res == CSELECT_ERR) {

    failf(data, "select/poll returned error");

    return CURLE_SEND_ERROR;

  }

Stepping into Curl_select

do {

    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err,
&timeout);

  } while((r == -1) && (Curl_sockerrno() == EINTR));

 

  if (r < 0)

    return -1;

  if (r == 0)

    return 0; - this returns 0.

 

3. within the do while loop

 

  do {

    /* If we still have reading to do, we check if we have a readable

       socket. */

    if((k->keepon & KEEP_READ) && (select_res & CSELECT_IN)) {

 condition does not pass. So block is skipped.

 

4. if((k->keepon & KEEP_WRITE) && (select_res & CSELECT_OUT)) {

Condition does not pass

5.

k->now = Curl_tvnow();

  if(didwhat) {

    /* Update read/write counters */

    if(conn->bytecountp)

      *conn->bytecountp = k->bytecount; /* read count */

    if(conn->writebytecountp)

      *conn->writebytecountp = k->writebytecount; /* write count */

  }

  else {

it executes the else part - I have not set a timeout value and

 

 

  if(Curl_pgrsUpdate(conn))

    result = CURLE_ABORTED_BY_CALLBACK;

  else

    result = Curl_speedcheck(data, k->now);

  if (result)

    return result;

 

  if (data->set.timeout &&

      ((Curl_tvdiff(k->now, k->start)/1000) >= data->set.timeout)) {

    failf(data, "Operation timed out with %" FORMAT_OFF_T

          " out of %" FORMAT_OFF_T " bytes received",

          k->bytecount, conn->size);

    return CURLE_OPERATION_TIMEOUTED;

  }

Sets result to OK - Curl speedcheck is executed.

 

6.

if(!k->keepon) { - check does not pass

 

  /* Now update the "done" boolean we return */

  *done = !k->keepon; - which is set to true and the whole loop
continues again.

 

Would you please let me know if this is a problem with CURL code or
there is some inconsistency in the driver below that is causing this?

 

On another system type where it does work if(!k->keepon is false and
Partial_file is returned.

 

Keepon is reset if the socket has a valid read or a valid write value
returned in Curl_Select.

But here that returns 0.

Is that return code correct?

If so, should the value of keepon or done change if both read and write
are not valid i.e curl_select returns 0.

I think in this case done should be set to false but I am not sure of
the impact it will have on other cases.

 

Thanks very much for your help.

 

Regards,

Sonia.

 

 

 

 

 
Received on 2007-04-18