You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WSAEventSelect标记就绪后,ReadFile仍发生挂起的场景有哪些?

安全扫描软件触发的TCP套接字挂起问题分析

这一问题颇为棘手。我们遇到了由某款安全扫描软件引发(确切说是触发)的异常挂起情况。怀疑该软件采用了非标准TCP/IP栈,客户正询问挂起原因。

静态分析显示挂起仅可能出现在两个位置:套接字的ReadFile()或WriteFile()操作中;除非扫描软件故意将窗口大小设为0,否则WriteFile()不会在此处挂起。即便WriteFile()未取得进展但能返回,我也能解除程序的阻塞状态,且日志状态也与WriteFile()返回的情况不符。

接下来分析ReadFile(),以下是调用序列:

SOCKET conn;
HANDLE unwedgeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE listenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (listenEvent == NULL) return;
//...
conn = accept(lstn);
for (;;) {
    HANDLE wakeup[2];
    wakeup[0] = unwedgeEvent;
    wakeup[1] = listenEvent;
    if (WSAEventSelect(conn, socket, FD_READ | FD_CLOSE) == 0) {
        // Log error 
        break;
    }
    which = WaitForMultipleObjects(2, wakeup, FALSE, INFINITE);
    if (which < 0) {
       // Log error
       break;
    }
    if (which == 1) {
        DWORD read;
        r = ReadFile(conn, chunk, 4096, &read, NULL);
        if (r == 0) {
            // Handle error -- not stuck here
        } else {
            // Handle data -- not stuck here either
        }
    }
    if (which == 0) break;
}

在此场景下,触发unwedgeEvent无法起到任何作用,线程会永久阻塞。

所以我真正的疑问是:这真的可能发生,还是我搞错了?

目前问题已陷入僵局;我完全不需要非阻塞套接字,只需要一个能同时处理套接字和非套接字句柄的select()函数。

以下API调用序列不会导致ReadFile挂起:

---------------------------------------------------------------
Sender                                 B Receiver
                                         WSAEventSelect
                                       * WaitForMultipeObjects
send(buffer size = 1)
                                         ReadFile(size = 1)
                                         WSAEventSelect
                                       * WaitForMultipeObjects
send(buffer size = 1)
                                         ReadFile(size = 1)
................................................................
                                         WSAEventSelect
                                       * WaitForMultipeObjects
send(buffer size = 2)
                                         ReadFile(size = 1)
                                         WaitForMultipeObjects
                                         ReadFile(size = 1)
................................................................
                                         WSAEventSelect
                                       * WaitForMultipeObjects
send(buffer size = 1)
send(buffer size = 1)
                                         ReadFile(size = 1)
                                         WaitForMultipeObjects
                                         ReadFile(size = 1)
................................................................
                                         WSAEventSelect
send(buffer size = 1)
                                         WaitForMultipeObjects
send(buffer size = 1)
                                         ReadFile(size = 1)
                                         WaitForMultipeObjects
                                         ReadFile(size = 1)
................................................................
                                         WSAEventSelect
send(buffer size = 1)
                                         WaitForMultipeObjects
send(buffer size = 1)
                                         ReadFile(size = 2)
                                       * WaitForMultipeObjects
send(buffer size = 1)
                                         ReadFile(size = 1)
................................................................
                                         WSAEventSelect
send(buffer size = 1)
                                         WaitForMultipeObjects
                                         ReadFile(size = 1)
send(buffer size = 1)
                                         WaitForMultipeObjects
                                         ReadFile(size = 1)

内容的提问来源于stack exchange,提问作者Joshua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:41:07