开发者

select() times out immediately after long runtime (C++)

开发者 https://www.devze.com 2023-02-21 04:15 出处:网络
Most of the time this code works just fine. But sometimes when the executable has been running for a while, select() appears to time out immediately, then get into a weird state where it keeps getting

Most of the time this code works just fine. But sometimes when the executable has been running for a while, select() appears to time out immediately, then get into a weird state where it keeps getting called, timing out immediately, over and over. Then it has to be killed from the outside.

My guess would be that the way that standard input changes overtime is at fault - that is what select is blocking on.

Looking around on StackOverflow, most of people's select() troubles seem to be solved by making sure to reset with the macros (FD_ZERO & FD_SET) every time and using the right initial parameter to select. I don't think those are the issues here.

int            rc     = 0;
fd_set 开发者_如何学Python        fdset;
struct timeval timeout;

// -- clear out the response -- //
readValue = "";

// -- set the timeout -- //
timeout.tv_sec = passedInTimeout;  // 5 seconds
timeout.tv_usec = 0;

// -- indicate which file descriptors to select from -- //
FD_ZERO(&fdset);
FD_SET(passedInFileDescriptor, &fdset); //passedInFileDescriptor = 0

// -- perform the selection operation, with timeout -- //
rc = select(1, &fdset, NULL, NULL, &timeout);


if (rc == -1)  // -- select failed -- //
{
    result = TR_ERROR;
}
else if (rc == 0)  // -- select timed out -- //
{
    result = TR_TIMEDOUT;
}
else 
{
    if (FD_ISSET(mFileDescriptor, &fdset))
    {
        if(rc = readData(readValue) <= 0)
        {
            result = TR_ERROR;
        }
    } else {
       result = TR_SUCCESS;
    }
}


Beware that some implementaions of "select" apply strictly the specification: "nfds is the highest-numbered file descriptor in any of the three sets, plus 1". So, you'd better to change "1" with "passedInFileDescriptor+1" as first parameter. I don't know if this can solve your problem, but at least your code becomes more... uhm... "traditional" ;)

Bye


On some OSes, timeout is modified when calling select to reflect the amount of time not slept. It doesn't look like you're reusing timeout in your example, but make sure that you are indeed reinitializing it to 5 seconds every time before calling select.


I'm having the same problem, it works fine on windows but not on linux and I have the maxfd set to last socket + 1. It occurs periodically after long runs. I pick up the connection on accept and then the first call to select periodically times out.


Look at this code:

if (FD_ISSET(mFileDescriptor, &fdset))
{
    if(rc = readData(readValue) <= 0)
    {
        result = TR_ERROR;
    }
} else { 
   result = TR_SUCCESS;
}

There are two things bothering me here:

  1. if your FD has no data in it (like, say, an error occured), FD_ISSET() will return false and your function returns TR_SUCCESS !?
  2. you FD_SET(passedInFileDescriptor, &fdset), but check on another value: FD_ISSET(mFileDescriptor, &fdset). If mFileDescriptor != passedInFileDescriptor at some point, you'll fall into my first assumption.

It should be looking like this:

if (FD_ISSET(passedInFileDescriptor, &fdset))
{
    if(rc = readData(readValue) <= 0)
    {
        result = TR_ERROR;
    }
    else 
    {
        result = TR_SUCCESS;
    }
}
else
{
    result = TR_ERROR;
}

No?

(Edit: also, this answer also points the problem of your use of select() with a bad high_fd value)

Another edit: well, looks like the guys never came back... frustrating.

0

精彩评论

暂无评论...
验证码 换一张
取 消