2

ほとんどの場合、このコードは問題なく動作します。しかし、実行可能ファイルがしばらく実行されていると、select() がすぐにタイムアウトしたように見え、その後、呼び出され続けるという奇妙な状態になり、すぐにタイムアウトを何度も繰り返すことがあります。それからそれは外側から殺されなければなりません。

私の推測では、標準入力が時間の経過とともに変化する方法に問題があると思います-それがselectがブロックしているものです。

StackOverflow を見回すと、select() に関する問題のほとんどは、毎回マクロ (FD_ZERO & FD_SET) でリセットし、適切な初期パラメーターを使用して選択することで解決されるようです。それらはここでの問題ではないと思います。

int            rc     = 0;
fd_set         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;
    }
}
4

4 に答える 4

1

私は同じ問題を抱えています.Windowsでは正常に動作しますが、Linuxでは動作せず、maxfdを最後のソケット+ 1に設定しています.長時間実行すると定期的に発生します. 私は受け入れ時に接続を取得し、選択するための最初の呼び出しが定期的にタイムアウトします。

于 2011-05-11T17:10:56.510 に答える
1

「select」の一部の実装では、仕様が厳密に適用されることに注意してください。「nfds は、3 つのセットのいずれかで最大の番号のファイル記述子に 1 を加えたものです」。したがって、最初のパラメーターとして「passedInFileDescriptor+1」を使用して「1」を変更することをお勧めします。これで問題が解決するかどうかはわかりませんが、少なくともコードはもっと...うーん...「伝統的」になります;)

さよなら

于 2011-04-01T21:06:28.057 に答える
1

一部の OS では、スリープしていない時間を反映するようtimeoutに呼び出し時に変更されます。select例で再利用しているようには見えませんがtimeout、呼び出す前に毎回 5 秒に再初期化していることを確認してくださいselect

于 2011-04-01T23:24:55.300 に答える
0

このコードを見てください:

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

ここで気になることが 2 つあります。

  1. FD にデータが含まれていない場合 (エラーが発生した場合など)、FD_ISSET() が返さfalseれ、関数は TR_SUCCESS!?を返します。
  2. FD_SET(passedInFileDescriptor, &fdset)、しかし別の値を確認してください: FD_ISSET(mFileDescriptor, &fdset)。もしmFileDescriptor != passedInFileDescriptorがある時点で、あなたは私の最初の仮定に陥るでしょう。

次のようになります。

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

いいえ?

(編集:また、この回答select()は、不適切なhigh_fd値での使用の問題も指摘しています)

別の編集: うーん、みんな戻ってこなかったように見えます... イライラします.

于 2011-08-17T14:12:29.603 に答える