Perl STDIN 在后台挂起,在前台工作正常

标签 perl stdin

这是我的程序

my $input;
my $finish = 0;
my $timer = 5; # 5 seconds
eval {
    while( ! $finish ) {
        local $SIG{ALRM} = sub {
          # check counter and set alarm again
          if (--$timer) { alarm 1 }
          # no more waiting
          else { die "timeout getting the input \n" }
        };
        # alarm every second
        alarm 1;
        $input = <STDIN>;
        alarm 0;
        if ( $input ) {
            chomp $input;
            if( $input ){
                print( "Received input : $input" );
                $finish = 1;
            } else {
                print( "Please enter valid input" );
            }
        } else {
            print( "input is undefined" );
            last;
        }
    }
};

if ($@ || !$input) {
    print( "Timeout in getting input." );
    return undef;
}

return $input;

STDIN 在前台工作正常。但在后台运行相同的程序时失败。逻辑是如果用户在 5 秒内没有输入任何输入,则退出循环。但是当在后台运行时,进程应该在 x 秒内退出,但进程卡在 <STDIN> 行中。

如何解决这个问题?

最佳答案

当后台进程尝试终端输入时,它会收到信号SIGTTIN,该信号的默认操作为“停止”——即进程暂停,就像它收到一样>SIGSTOP。由于它已停止,因此它没有机会处理警报、退出或执行任何其他操作。

因此,您需要设置一个 SIGTTIN 处理程序来覆盖默认的停止行为。

您可以做的最简单的事情是 local $SIG{TTIN} = 'IGNORE'; 这会导致信号被忽略。然后,STDIN 的读取将立即失败(返回 undef,$! 设置为 EIO),并且您会遇到“输入未定义”的情况代码中的情况。

您还可以设置 local $SIG{TTIN} = sub { die "process is backed"}; 这可以让您更清楚地区分这种情况。

或者您可以使用信号处理程序设置一些巧妙的东西并重试读取,以便万一用户决定在超时到期之前后台并重新附加,他们仍然能够提供输入,但我保留了这一点由你决定。

关于Perl STDIN 在后台挂起,在前台工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45948646/

相关文章:

java - 如何在 Linux 终端上从 Java 标准输入中抑制或删除转义码字符

shell - 将标准输入和标准输出重定向到文件

linux - 为什么这个行编号命令会破坏字符编码?

bash - 当 Perl 嵌入到 shell 脚本中时,如何查看父脚本中用实际行号报告的语法错误?

perl - 如何访问 Mojolicious 模型中的 session 数据

c - 为什么我的 "dup2(STDIN_FILENO, fd)"不能向 grep 发送参数?

windows - 如何在 Windows 上读取 Perl 中的管道输入?

c++ - 如何在没有延迟的情况下从 Win32 中的另一个进程捕获标准输出?

perl - 让 Perl 将完整的 "key path"打印到值中(Data::Dumper 不会)

java - 我应该如何在 Java 中调用 Perl 脚本?