【问题标题】:SIGPIPE, Broken pipeSIGPIPE,断管
【发布时间】:2011-10-13 01:09:19
【问题描述】:

我正在 linux 机器上使用 epoll 开发一个网络程序,我从 gdb 收到错误消息。

Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0x7ffff609a700 (LWP 19788)]
0x00007ffff7bcdb2d in write () from /lib/libpthread.so.0
(gdb)
(gdb) backtrace
#0  0x00007ffff7bcdb2d in write () from /lib/libpthread.so.0
#1  0x0000000000416bc8 in WorkHandler::workLoop() ()
#2  0x0000000000416920 in WorkHandler::runWorkThread(void*) ()
#3  0x00007ffff7bc6971 in start_thread () from /lib/libpthread.so.0
#4  0x00007ffff718392d in clone () from /lib/libc.so.6
#5  0x0000000000000000 in ?? ()

我的服务器进行 n^2 次计算,我尝试运行有 500 个连接用户的服务器。什么可能导致此错误?我该如何解决这个问题?


       while(1){
            if(remainLength >= MAX_LENGTH)
                currentSentLength = write(client->getFd(), sBuffer, MAX_LENGTH);
            else
                currentSentLength = write(client->getFd(), sBuffer, remainLength);


            if(currentSentLength == -1){
                log("WorkHandler::workLoop, connection has been lost \n");
                break;
            }
            sBuffer += currentSentLength;
            remainLength -= currentSentLength;

            if(remainLength == 0)
                break;
        }

【问题讨论】:

  • SIGPIPE 在您尝试写入已关闭的管道时发生,请确保您正在写入的管道未关闭。
  • 将其发布为答案,以便我们对其进行投票。鉴于问题中的信息很少,这是尽可能多的答案。 @LCYSoft:如果没有调用函数的代码,GDB 跟踪将毫无用处。
  • 没有。发布一个测试用例。我们现在将得到数百条无用的行。

标签: c++ c linux networking


【解决方案1】:

当您写入已关闭的管道(由远程端)时,您的程序将收到此信号。对于简单的命令行过滤程序,这通常是适当的默认操作,因为 SIGPIPE 的默认处理程序将终止程序。

对于多线程程序,正确的操作通常是忽略 SIGPIPE 信号,这样写入关闭的套接字不会终止程序。

请注意,您无法在写入之前成功执行检查,因为远程端可能会在您检查和调用 write() 之间关闭套接字。

有关忽略 SIGPIPE 的更多信息,请参阅此问题:How to prevent SIGPIPEs (or handle them properly)

【讨论】:

  • 有时您会收到一个 SIGPIPE,因为远程端关闭了连接并且从未告诉过您。 系统崩溃会导致这种情况很多,因为它们不会清理打开的套接字,所以您不知道套接字已经消失,直到您向其写入内容并且远程端声称不知道连接。
  • 你可以成功执行检查就好了;你只是不能有用地这样做。 :)
  • @Tomalak Geret'kal 不,你不能。除了尝试 I/O 操作之外,没有 Sockets API 会告诉您。
  • @EJP:呸,这可能是真的。至少,您在答案第三段中给出的理由不是正当理由。 :)
  • @Tomalak Geret'kal 真的。没有“可能”。我假设您参考了 Greg Hewgill 的回答中的第三段
【解决方案2】:

您没有捕捉到SIGPIPE 信号,但您正在尝试写入已损坏/关闭的管道。

相当不言自明。

通常将SIGPIPE 信号作为无操作处理就足够了,并以您需要的任何特定于应用程序的方式处理write 调用周围的错误情况...例如this

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 2012-07-03
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2018-06-08
    相关资源
    最近更新 更多