- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下问题是对 this 答案中有关死锁的评论的回应。很好奇死锁是怎么来的,所以我创建了一个测试程序:有一个父进程向子进程的STDIN写入大量数据,而子进程也向父进程的reader句柄写入大量数据。原来如果数据大小超过80K就会出现死锁(Ubuntu 16.04):
parent.pl :
use feature qw(say);
use strict;
use warnings;
use IPC::Open2;
my $test_size = 80_000; # How many bytes to write?
my $pid = open2( my $reader, my $writer, 'child.pl' );
my $long_string = '0123456789' x ($test_size / 10);
printf "Parent: writing long string ( length: %d )\n", length $long_string;
print $writer $long_string;
close $writer;
say "Parent: Trying to read childs ouput..";
my $output = do { local $/; <$reader> };
printf "Parent: Got output with length %d..\n", length $output;
close $reader;
say "Parent: Reaping child..";
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
say "Parent: Child exited with status: $child_exit_status";
use feature qw(say);
use strict;
use warnings;
my $test_size = 80_000; # How many bytes to write?
my $child_log_filename = 'childlog.txt';
open ( my $log, '>', $child_log_filename ) or die "Could not create log file: $!";
say $log "Child is running..";
my $long_string = '0123456789' x ($test_size / 10);
say $log "Length of output string: " . length $long_string;
say $long_string;
my $input = do { local $/; <STDIN> };
say $log "Length of input string: " . length $input;
exit 2;
最佳答案
死锁的原因似乎是管道在写入时被填满,没有人从中读取。根据 pipe(7) :
If a process attempts to write to a full pipe (see below), then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete.
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the O_NONBLOCK flag is set. Different implementations have different limits for the pipe capacity. Applications should not rely on a particular capacity: an application should be designed so that a reading process consumes data as soon as it is available, so that a writing process does not remain blocked.
In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11, the pipe capacity is 65536 bytes. Since Linux 2.6.35, the default pipe capacity is 65536 bytes
select
、
fcntl
、
sysread
和
syswrite
来解决这个问题。由于如果我们尝试写入超过管道容量的内容,
syswrite
会阻塞,因此我使用
fcntl
使编写器处理非阻塞。在这种情况下,
syswrite
将尽可能多地写入管道,然后立即返回实际写入的字节数。
parent.pl
需要更改(这也是需要的,因为我们不应该假设可以访问 child 的源代码)。这是
parent.pl
将防止死锁:
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; # How many bytes to write?
my $pid = open2( my $reader, my $writer, 'child.pl' );
make_filehandle_non_blocking( $writer );
my $long_string = '0123456789' x ($test_size / 10);
printf "Parent: writing long string ( length: %d )\n", length $long_string;
my $sel_writers = IO::Select->new( $writer );
my $sel_readers = IO::Select->new( $reader );
my $read_offset = 0;
my $write_offset = 0;
my $child_output = '';
while (1) {
last if $sel_readers->count() == 0 && $sel_writers->count() == 0;
my @sel_result = IO::Select::select( $sel_readers, $sel_writers, undef );
my @read_ready = @{ $sel_result[0] };
my @write_ready = @{ $sel_result[1] };
if ( @write_ready ) {
my $bytes_written = syswrite $writer, $long_string, WRITE_BUF_SIZE, $write_offset;
if ( !defined $bytes_written ) {
die "syswrite failed: $!" if $! != EAGAIN;
$bytes_written = 0;
}
$write_offset += $bytes_written;
if ( $write_offset >= length $long_string ) {
$sel_writers->remove( $writer );
close $writer;
}
}
if ( @read_ready ) {
my $bytes_read = sysread $reader, $child_output, READ_BUF_SIZE, $read_offset;
if ( !defined $bytes_read ) {
die "sysread failed: $!" if $! != EAGAIN;
$bytes_read = 0;
}
elsif ( $bytes_read == 0 ) {
$sel_readers->remove( $reader );
close $reader;
}
$read_offset += $bytes_read;
}
}
printf "Parent: Got output with length %d..\n", length $child_output;
say "Parent: Reaping child..";
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
say "Parent: Child exited with status: $child_exit_status";
sub make_filehandle_non_blocking {
my ( $fh ) = @_;
my $flags = fcntl $fh, F_GETFL, 0
or die "Couldn't get flags for file handle : $!\n";
fcntl $fh, F_SETFL, $flags | O_NONBLOCK
or die "Couldn't set flags for file handle: $!\n";
}
关于perl - 由于缓冲导致死锁。它是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40189625/
我正在使用 MediaPlayer 在我的应用程序中播放在线 mp3 文件中的一些声音。 但是,即使在播放完成后,我也会在控制台中收到一行又一行的回调和缓冲。 10-24 08:08:48.467
我有一个简单的多边形。 dfr p = st_polygon(list(as.matrix(dfr))) > pbuf = st_buffer(p, .4) > plot(pbuf) > plot(
这可能又是一些愚蠢的问题,也许这确实是我所缺少的东西,但我很难让 glMultiDrawArrays 在 OpenGL4 中工作。 我发现了很多这样的解释: for (int i = 0; i #i
这仅仅是根据网络速度调整预缓冲内容量的问题吗?你是否在一开始就为此调整一次,每秒......? 或者它更复杂 - 对您的网络速度记录历史进行采样并取平均值/中值并对其进行调整? 最佳答案 您的第二段总
嗨,我正在使用 FFmpeg Autogen C#。当我使用 mkv 输出作为文件并使用 h264 rtsp 流作为输入时,一切正常。编解码器是 libx264 ffmpeg.avio_open(
我需要多次遍历几个文本文件的行。目前这是通过多个 with open("file.txt") as f: for line in f: # do something 虽然性能还
昨天给同学们写了一个xinetd小练习:做一个反向回显程序。 为了学习新东西,我尝试实现一个 Haskell 解决方案。琐碎的main = forever $ interact reverse不起作用
我正在阅读《实时渲染第三版》中的遮挡剔除部分,但我无法理解它是如何工作的。一些问题: “Z 金字塔”有何贡献?为什么我们需要多种分辨率的 Z 缓冲区?在书中,它的显示如下(左侧): 八叉树结构与用于一
我通过串行端口与设备通信。 我已成功获取 InputStream 并读取设备发送的内容。 但问题是,我根本不知道何时停止阅读并继续执行另一项任务。 这是简化的代码: inputStream = ser
我有以下代码: func (q *Queue) GetStreams(qi *QueueInfo) { channel := make(chan error, len(qi.AudioChun
在我调用 -play 之前,有没有办法让 MPMusicPlayerController 缓冲内容?还是在您设置队列时默认执行此操作? AVAudioPlayer 有 -prepareToPlay 方
我正在编写一个数据库 备份函数,从System.Diagnostics.Process 对象 读取StandardOutput (StreamReader) 属性。我已成功写入普通文件。 //This
我有一个 wpf 应用程序,其中所有 viewModel 都继承自实现 INotifyPropertyChanged 的类 NotifyPropertyChangeClass(见下文)。 我想限制
我需要类似于 withLatestFrom 的东西,对应于下图: ---------A-----------------B-- -1-2-3------4------5-6-7-8---- -----
有没有办法缓冲 OutputStream,在返回之前修改它?这是我的代码片段: public ServletOutputStream getOutputStream() throws IOExcept
目前我们有实现服务器通信协议(protocol)缓冲的需求。如果有人对此有任何意见,他们可以向我提供任何意见吗。 最佳答案 请查看以下 Protocol Buffer 链接。 http://code.
所以我目前正在开发一个 Java 应用程序,该应用程序应该将特定事件记录到数据库中。我希望每分钟最多有 15 到 20 次插入,基本上我想知道我是否应该为每个插入语句建立一个新连接,或者只要应用程序正
请考虑以下代码,包括两个线程 buffering_thread(用一条消息填充缓冲区指针)和 sending_thread(清空缓冲区): #include "msg.cpp" msg * buffe
是否可以在线播放由两个或多个视频文件组成的视频? 由于我原来的帖子不够清楚,这里有扩展的解释和问题。 我的站点托管在 Linux/Apache/PHP 服务器上。我有 FLV/F4V 格式的视频文件。
这是我用于缓冲和转换传入事件的代码: public Publisher> logs(String eventId) { ConnectableObservable connectableObs
我是一名优秀的程序员,十分优秀!