select()永远挂起的问题

4

我有一个运行在嵌入式linux上的应用程序(较旧的内核,2.6.18)。 我正在使用Live555。 偶尔当摄像头负载很重时,我的RTSP服务器(使用Live555构建)将无限期挂起-除了重置应用程序外,没有任何连接或哄骗似乎能使其恢复。

我将故障定位到这段代码:

static int blockUntilReadable(UsageEnvironment& env,
                  int socket, struct timeval* timeout) {
  int result = -1;
  do {
    fd_set rd_set;
    FD_ZERO(&rd_set);
    if (socket < 0) break;
    FD_SET((unsigned) socket, &rd_set);
    const unsigned numFds = socket+1;

    result = select(numFds, &rd_set, NULL, NULL, timeout);  <--HANG

超时时间当然是一个空指针,表示应该一直阻塞,直到其中一个套接字可读。问题是:无论我是否连接到RTSP服务器,它都会无限期地阻塞。

我执行了netstat -an命令,它总是输出类似以下内容:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:5222            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:5800            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:5802            0.0.0.0:*               LISTEN
tcp       21      0 0.0.0.0:554             0.0.0.0:*               LISTEN

当它处于失败状态时,我总是看到 Recv-Q 上的 21,这是“与此套接字连接的用户程序未复制的字节数”的计数。

有人知道可能出了什么问题,或者我该如何排除故障?

1个回答

2

那段代码看起来很可靠。我有点好奇你为什么要转换成unsigned int,但这不应该有任何影响。

以下是一些想法:

它没有挂在你认为的地方。希望你已经进行了双倍/三倍的检查。(再次检查?)

你对netstat的解释是错误的。正如man页面所指出的那样,该部分是针对“已建立”的套接字 - 你的是一个监听器,即下一句话:“正在侦听:自内核2.6.18以来,此列包含当前的syn后退。”

那看起来像是一个巨大的后退……这让我想到你可能没有接受(accept()),也许是因为你被困在select()中。那个 就是 你监听套接字上的select(),对吗?

最后,请仔细检查你是否在正确的套接字上调用了select()。即,打印出该套接字参数,并查看它是否符合要求。

基本上,验证:1)它是否在select()中挂起,以及2)select的参数是否正确。我怀疑其中之一是不正确的。


“socket是监听/接受套接字吗?” 这也是我的第一个想法。 - Chris Johnsen
我的怀疑是 socket 在这里得到了一个错误的值。 - caf
感谢Thanatos。顺便说一下,这不是我的代码 - 它是开源RTSP库Live555的一部分。我确定它在select()中挂起。我不确定select的参数是否正确,所以我会验证一下。还要感谢您提醒我关于netstat更改的事情。 - kidjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接