perl tk fileevent 在第二个事件上失败
perl tk fileevent fail on the second event
这个简单的摘录,运行 在 Perl 5.16.3 上,在打开时分叉了一个子进程,该子进程将数据发送到主进程。
#!/usr/bin/perl
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
my $fh;
sub receiver()
{
print "$_" while <$fh>;
print "End\n";
close $fh;
}
sub run()
{
print "run\n";
my $pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', \&receiver);
}
仅第一次按预期工作,第二次单击打开按钮时产生:
Tk::Error: Can't locate object method "OPEN" via package "Tk::Event::IO" at fe.pl line 16.
Tk callback for .button
Tk::ANON at /usr/lib64/perl5/vendor_perl/Tk.pm line 251
Tk::Button::butUp at /usr/lib64/perl5/vendor_perl/Tk/Button.pm line 175
(command bound to event)
我正在努力理解原因,但没有成功。有什么想法吗?
Tk::Error: Can't locate object method "OPEN" via package "Tk::Event::IO"
似乎你需要在每次完成 receiver
时删除 fileevent
处理程序,否则 Tk
稍后将尝试再次调用回调(使用相同的您刚刚在接收器中关闭的文件句柄)但是文件句柄不再有效。
以下对我有用:
use strict;
use warnings;
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
sub run()
{
my $fh;
my $receiver = sub {
print "$_" while <$fh>;
print "End\n";
close $fh;
# delete handler since $fh is no longer used
$mainWindow->fileevent($fh, "readable", "");
};
print "run\n";
my $pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', $receiver);
}
#!/usr/bin/perl
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
sub run()
{
my $fh;
my $pid;
$SIG{CHLD} = sub
{
my $kid = waitpid(-1, WNOHANG);
print "$kid exited with $? ${^CHILD_ERROR_NATIVE}\n"
};
my $receiver = sub
{
print "$_" while <$fh>;
print "End\n";
close $fh;
# delete handler since $fh is no longer used
$mainWindow->fileevent($fh, 'readable', '');
};
print "run\n";
$pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', $receiver);
}
这个简单的摘录,运行 在 Perl 5.16.3 上,在打开时分叉了一个子进程,该子进程将数据发送到主进程。
#!/usr/bin/perl
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
my $fh;
sub receiver()
{
print "$_" while <$fh>;
print "End\n";
close $fh;
}
sub run()
{
print "run\n";
my $pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', \&receiver);
}
仅第一次按预期工作,第二次单击打开按钮时产生:
Tk::Error: Can't locate object method "OPEN" via package "Tk::Event::IO" at fe.pl line 16. Tk callback for .button Tk::ANON at /usr/lib64/perl5/vendor_perl/Tk.pm line 251 Tk::Button::butUp at /usr/lib64/perl5/vendor_perl/Tk/Button.pm line 175 (command bound to event)
我正在努力理解原因,但没有成功。有什么想法吗?
Tk::Error: Can't locate object method "OPEN" via package "Tk::Event::IO"
似乎你需要在每次完成 receiver
时删除 fileevent
处理程序,否则 Tk
稍后将尝试再次调用回调(使用相同的您刚刚在接收器中关闭的文件句柄)但是文件句柄不再有效。
以下对我有用:
use strict;
use warnings;
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
sub run()
{
my $fh;
my $receiver = sub {
print "$_" while <$fh>;
print "End\n";
close $fh;
# delete handler since $fh is no longer used
$mainWindow->fileevent($fh, "readable", "");
};
print "run\n";
my $pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', $receiver);
}
#!/usr/bin/perl
use Tk;
my $mainWindow = MainWindow->new();
$mainWindow->Button(-text => "Run", -command => \&run)->pack();
MainLoop;
sub run()
{
my $fh;
my $pid;
$SIG{CHLD} = sub
{
my $kid = waitpid(-1, WNOHANG);
print "$kid exited with $? ${^CHILD_ERROR_NATIVE}\n"
};
my $receiver = sub
{
print "$_" while <$fh>;
print "End\n";
close $fh;
# delete handler since $fh is no longer used
$mainWindow->fileevent($fh, 'readable', '');
};
print "run\n";
$pid = open $fh, '-|';
die "Failed to start\n" unless defined $pid;
print "pid=$pid\n";
exec "echo Hello" unless $pid;
$mainWindow->fileevent($fh, 'readable', $receiver);
}