SIGPIPE,破损的管道

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;
        }

6
当您尝试向已关闭的管道写入数据时,会发生SIGPIPE错误,请确保您要写入的管道未关闭。 - Jesus Ramos
@LCYSoft:如果没有调用函数的代码,GDB跟踪就毫无意义。 - Mike DeSimone
不要发一个测试用例。现在我们会得到数百行无用的代码。 - Lightness Races in Orbit
2个回答

34

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

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

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

有关忽略SIGPIPE的更多信息,请参见此问题:如何防止SIGPIPE(或正确处理它们)


有时候你会收到SIGPIPE信号,因为远程端关闭了连接而没有告诉你。系统崩溃经常会导致这种情况,因为它们不清理打开的套接字,所以你不知道套接字已经关闭直到你向其写入数据,而远程端否认对该连接的了解。 - Mike DeSimone
2
你可以成功地执行检查,但你不能有用地这样做。 :) - Lightness Races in Orbit
@Tomalak Geret'kal 你不行。除非尝试I/O操作,否则没有套接字API可以告诉你。 - user207421
@EJP:嗯,也许是这样。至少,你在回答的第三段中给出的理由不是一个有效的理由。 :) - Lightness Races in Orbit
@Tomalak Geret'kal,这是真的。没有任何“可能”的问题。我猜你指的是Greg Hewgill答案中的第三段? - user207421

2
你没有捕获SIGPIPE信号,但是你试图向一个已经被破坏/关闭的管道写入数据。
这个问题比较明显。
通常情况下,将处理SIGPIPE信号作为无操作,然后在你需要的应用程序特定方式中处理write调用的错误情况就足够了...就像this

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