是什么原因导致管道破裂?

时间:2022-11-09 15:39:08

I know that broken pipe error is thrown when the socket on the peer side is closed.

我知道,当对等端上的套接字关闭时,会引发管道错误。

But, in my test I have noted that an immediate 'send' call on this side when the peer side is closed doesn't always lead to a broken pipe error.

但是,在我的测试中,我注意到,当对等方关闭的时候,立即发出“发送”调用,并不总是导致管道错误。

E.g.:

例如:

After closing the socket on peer side (I have tried clean closing by calling close and also abnormal closing by killing the peer), if I try to send 40 bytes, then I don't get a broken pipe, but, if I try to send 40000 bytes then it immediately gives broken pipe error.

关闭套接字后端(我试过清洁关闭通过调用关闭,也异常关闭,通过杀同行),如果我试着发送40字节,那么我不要管破裂,但是,如果我试着发送40000字节就立即给破管错误。

What exactly causes broken pipe and can it's behavior be predicted?

到底是什么导致了破裂的管道,它的行为能被预测吗?

3 个解决方案

#1


39  

It can take time for the network close to be observed - the total time is nominally about 2 minutes (yes, minutes!) after a close before the packets destined for the port are all assumed to be dead. The error condition is detected at some point. With a small write, you are inside the MTU of the system, so the message is queued for sending. With a big write, you are bigger than the MTU and the system spots the problem quicker. If you ignore the SIGPIPE signal, then the functions will return EPIPE error on a broken pipe - at some point when the broken-ness of the connection is detected.

网络接近被观察到需要时间——总时间名义上大约是2分钟(是的,分钟!),然后在发送到端口的数据包都被认为是死的。在某个点检测到错误条件。有了一个小的写,您就在系统的MTU中,所以消息被排队等待发送。有了大的写作,你比MTU更大,系统会更快地发现问题。如果您忽略了SIGPIPE信号,那么当检测到连接的故障时,函数将返回一个破裂的管道上的EPIPE错误。

#2


6  

The current state of a socket is determined by 'keep-alive' activity. In your case, this is possible that when you are issuing the send call, the keep-alive activity tells that the socket is active and so the send call will write the required data (40 bytes) in to the buffer and returns with out giving any error.

套接字的当前状态是由“keep-alive”活动决定的。在您的情况下,当您发出send调用时,keepalive活动会告诉您该套接字是活动的,因此发送调用将在缓冲区中写入所需的数据(40字节)并返回,并给出任何错误。

When you are sending a bigger chunk, the send call goes in to blocking state.

当您发送较大的块时,发送调用进入到阻塞状态。

The send man page also confirms this:

发送人页面也确认了这一点:

When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in non-blocking I/O mode. In non-blocking mode it would return EAGAIN in this case

当消息不符合套接字的发送缓冲区时,发送()通常是块,除非该套接字被放置在非阻塞I/O模式中。在非阻塞模式下,它会在这种情况下返回EAGAIN。

So, while blocking for the free available buffer, if the caller is notified (by keep-alive mechanism) that the other end is no more present, the send call will fail.

因此,在对空闲可用缓冲区进行阻塞时,如果调用者被通知(通过保持机制),另一端不再存在,则发送调用将失败。

Predicting the exact scenario is difficult with the mentioned info, but I believe, this should be the reason for you problem.

虽然上面提到的信息很难预测准确的场景,但我相信,这应该是你问题的原因。

#3


3  

Maybe the 40 bytes fits into the pipe buffer, and the 40000 bytes doesn't?

也许这40个字节适合于管道缓冲区,而40000字节没有?

Edit:

编辑:

The sending process is sent a SIGPIPE signal when you try to write to a closed pipe. I don't know exactly when the signal is sent, or what effect the pipe buffer has on this. You may be able to recover by trapping the signal with the sigaction call.

当您试图写入一个闭管道时,发送过程将发送一个SIGPIPE信号。我不知道信号是什么时候发出的,也不知道管道缓冲对这个有什么影响。您可以通过用sigaction调用捕获信号来恢复。

#1


39  

It can take time for the network close to be observed - the total time is nominally about 2 minutes (yes, minutes!) after a close before the packets destined for the port are all assumed to be dead. The error condition is detected at some point. With a small write, you are inside the MTU of the system, so the message is queued for sending. With a big write, you are bigger than the MTU and the system spots the problem quicker. If you ignore the SIGPIPE signal, then the functions will return EPIPE error on a broken pipe - at some point when the broken-ness of the connection is detected.

网络接近被观察到需要时间——总时间名义上大约是2分钟(是的,分钟!),然后在发送到端口的数据包都被认为是死的。在某个点检测到错误条件。有了一个小的写,您就在系统的MTU中,所以消息被排队等待发送。有了大的写作,你比MTU更大,系统会更快地发现问题。如果您忽略了SIGPIPE信号,那么当检测到连接的故障时,函数将返回一个破裂的管道上的EPIPE错误。

#2


6  

The current state of a socket is determined by 'keep-alive' activity. In your case, this is possible that when you are issuing the send call, the keep-alive activity tells that the socket is active and so the send call will write the required data (40 bytes) in to the buffer and returns with out giving any error.

套接字的当前状态是由“keep-alive”活动决定的。在您的情况下,当您发出send调用时,keepalive活动会告诉您该套接字是活动的,因此发送调用将在缓冲区中写入所需的数据(40字节)并返回,并给出任何错误。

When you are sending a bigger chunk, the send call goes in to blocking state.

当您发送较大的块时,发送调用进入到阻塞状态。

The send man page also confirms this:

发送人页面也确认了这一点:

When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in non-blocking I/O mode. In non-blocking mode it would return EAGAIN in this case

当消息不符合套接字的发送缓冲区时,发送()通常是块,除非该套接字被放置在非阻塞I/O模式中。在非阻塞模式下,它会在这种情况下返回EAGAIN。

So, while blocking for the free available buffer, if the caller is notified (by keep-alive mechanism) that the other end is no more present, the send call will fail.

因此,在对空闲可用缓冲区进行阻塞时,如果调用者被通知(通过保持机制),另一端不再存在,则发送调用将失败。

Predicting the exact scenario is difficult with the mentioned info, but I believe, this should be the reason for you problem.

虽然上面提到的信息很难预测准确的场景,但我相信,这应该是你问题的原因。

#3


3  

Maybe the 40 bytes fits into the pipe buffer, and the 40000 bytes doesn't?

也许这40个字节适合于管道缓冲区,而40000字节没有?

Edit:

编辑:

The sending process is sent a SIGPIPE signal when you try to write to a closed pipe. I don't know exactly when the signal is sent, or what effect the pipe buffer has on this. You may be able to recover by trapping the signal with the sigaction call.

当您试图写入一个闭管道时,发送过程将发送一个SIGPIPE信号。我不知道信号是什么时候发出的,也不知道管道缓冲对这个有什么影响。您可以通过用sigaction调用捕获信号来恢复。