The reason for the deadlock is that the pipes are filled during recording, and no one reads them. According to pipe (7) :
If the process tries to write to the full channel (see below), then write (2) until a sufficient amount of data has been read so that the recording ends.
The pipe has a limited capacity. If the pipe is full, then record (2) will be blocked or malfunction, depending on whether the O_NONBLOCK flag is set. Different designs have different pipeline throughput limits. Applications should not rely on a specific capacity: the application should be designed so that the reading process consumes data as soon as it is available, so that the writing process does not remain blocked.
In versions of Linux prior to version 2.6.11, the pipe capacity was the same as the page size of the system (for example, 4096 bytes on the i386). Since Linux 2.6.11, the pipe capacity is 65536 bytes. Starting with Linux 2.6.35, the default capacity is 65536 bytes.
Therefore, the parent writes a long line to the child channel STDIN, the channel is filled, which leads to blocking the parent. At the same time, the child writes a long line to the channel for parents' readers, this is also filled, and the child block is blocked. Thus, the child waits for the parent to read from its reader channel, while the parent waits for the child to read its STDIN pipe. The so-called dead end.
I tried to solve this problem using select
, fcntl
, sysread
and syswrite
. Since syswrite
will block if we try to write more than the bandwidth of the channel, I used fcntl
to make the handler not block. In this case, syswrite
will write as much as possible to the pipe, and then immediately return with the number of bytes that it actually wrote.
Note: only parent.pl
needs to be changed (which is also necessary, since we should not assume that you have access to the original source). Here's the modified parent.pl
that will prevent deadlock:
use feature qw(say); use strict; use warnings; use Errno qw( EAGAIN ); use Fcntl; use IO::Select; use IPC::Open2; use constant READ_BUF_SIZE => 8192; use constant WRITE_BUF_SIZE => 8192; my $test_size = 80_000;