【问题标题】:WSASYSCALLFAILURE with overlapped IO on Windows XP在 Windows XP 上具有重叠 IO 的 WSASYSCALLFAILURE
【发布时间】:2010-07-16 08:25:48
【问题描述】:

我在代码中遇到了一个错误,该错误在重叠套接字上使用了 WSARecv 和 WSAGetOverlapped 结果。在重负载下,WSAGetOverlapped 返回 WSASYSCALLFAILURE('一个永远不会失败的系统调用失败'),然后我的 TCP 流不同步,导致我的程序的上层出现混乱。

到目前为止,我还无法将它与一组给定的硬件或驱动程序隔离开来。是否有人也遇到了这个问题,并找到了解决方案或解决方法?

【问题讨论】:

    标签: windows sockets winsock overlapped-io


    【解决方案1】:

    有多少连接、多少待处理的接收、多少发送? perfmon 或任务管理器对使用的非分页池的数量有何看法?盒子里有多少内存?如果您在 Vista 或更高版本上运行该程序,它会消失吗?你有安装任何 LSP 吗?

    您可能会耗尽非分页池,并导致写入错误的驱动程序在无法分配内存时出现异常行为。这个问题不太可能在 Vista 或更高版本上出现,因为可用的非分页池数量急剧增加(有关详细信息,请参阅http://www.lenholgate.com/blog/2009/03/excellent-article-on-non-paged-pool.html)。或者,您可能会达到“锁定页面”限制(您只能在操作系统的内存中锁定固定数量的页面,并且每个挂起的 I/O 操作会根据缓冲区大小和分配对齐方式锁定一个或多个页面)。

    【讨论】:

    • 大约 10 个连接,每个连接有一个待处理的接收。发送被实现阻塞,因此最多有一个未完成的发送。我稍后会检查其余的。在 Vista 上进行测试需要一些时间,因为我们还没有测试集群。感谢所有的指点 - 一旦我找到它,我会再次发布。
    • 那时不太可能是资源限制。可能只是一个坏司机?可以在不同网卡和驱动的机器上试一下吗?
    • 我们在不同的机器和驱动程序上始终存在问题。我开始认为 XP 上存在重叠 IO 的错误。我们的应用程序有些不同之处在于,一堆渲染从属设备将像素数据发送到一台机器,而不是服务器应用程序将数据发送到一堆客户端。
    • "XP 上 IO 重叠的错误" 如果是这样,我从来没有见过,我用重叠的套接字 IO 做了很多工作,并且已经做了 10 年左右。很可能您的代码中有错误,抱歉;)您可以发布一些代码来显示失败的区域吗?
    • 当然 - 连接在这里:equalizergraphics.com/cgi-bin/viewvc.cgi/trunk/src/lib/net/… 它在这里被 WaitForMultipleObjects 解复用:equalizergraphics.com/cgi-bin/viewvc.cgi/trunk/src/lib/net/… 并在这里从 Node::runReceiverThread/handleData 使用:equalizergraphics.com/cgi-bin/viewvc.cgi/trunk/src/lib/net/…
    【解决方案2】:

    看来我已经通过休眠 1ms 并在报告 WSASYSCALLFAILURE 时重试 WSAGetOverlapped 结果解决了这个问题。

    我遇到了另一个与触发重叠事件有关的问题,即使没有数据,我也必须先解决这个问题。测试现在运行了一个多小时,正确处理了一些 WSASYSCALLFAILURE。希望通宵测试也能成功。

    @Len:再次感谢您的帮助。

    编辑:通宵测试成功。我的错误是由两个相互依赖的问题引起的:

    问题 1:ConnectionSet::select 中的 WaitForMultipleObjects 偶尔 在空套接字上发送数据,导致 SocketConnection::readSync 到 僵局。 修复:对每个数据包的第一个字节进行非阻塞读取。重启 如果套接字为空,则连接设置

    问题 2:WSAGetOverlappedResult 偶尔返回 WSASYSCALLFAILURE, 导致 TCP 流不同步。 修复:一小段睡眠后重试 WSAGetOverlappedResult。

    http://equalizer.svn.sourceforge.net/viewvc/equalizer?view=revision&revision=4649

    【讨论】:

    • 嗯...我通常对需要睡眠的“修复”非常警惕...我希望您的代码中更有可能存在竞争条件并且您的“修复”会回来几年后当你转向你做梦也想不到的硬件时会咬你一口;)
    • 我大体上同意你们的 cmets,通常不会那样做“修复”。然而,在这种情况下,我已经将代码调试到死,并且相当确信这不是我的代码中的竞争。错误代码是 WSASYSCALLFAILURE,这是一个 Un-Error。此外,它仅在不寻常的通信模式下发生(许多节点向一个节点发送大量数据),这可能是它仍在 WinSocks 中的原因。我们之前在 Winsocks 上遇到过其他问题,例如,这个:mombu.com/microsoft/alt-winsock-programming/…
    • 再次,这看起来可能是一个竞争条件恕我直言......你怎么知道你的每次 i/o 何时完成,我没有看到任何引用计数正在进行,恕我直言,你需要对每个套接字和每个 i/o 数据进行引用计数,以确保您在正确的时间而不是之前清理...
    • 数据接收由单线程完成。数据被接收到一个 eq::net::Command 中,当它被插入到一个 net::CommandQueue 以被分派到处理线程时被引用,并在它被处理时被取消引用。 net::CommandCache 负责为 ReceiverThread 回收这些数据包。我在 Linux 上使用 valgrind 对这段代码进行了广泛的审查和测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 2011-12-31
    • 2010-09-08
    • 2012-06-09
    • 2014-02-10
    • 1970-01-01
    相关资源
    最近更新 更多