2017-08-29 61 views
2

罰款這是我的計劃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 ([email protected] || !$input) { 
    print("Timeout in getting input."); 
    return undef; 
} 

return $input; 

STDIN正常工作前景。但運行相同的程序背景時失敗。如果用戶在5秒內沒有輸入任何輸入,則邏輯將跳出循環。但在後臺運行時,該進程應在​​x秒內退出,但進程卡在<STDIN>行。

如何解決這個問題?

+1

每個程序在後臺掛起時都會掛在STDIN上。從哪裏得到它的輸入? – yacc

+0

用戶應該在x秒內輸入或程序應該退出while循環。由於這是在後臺,用戶輸入是不可能的,所以程序應該在x秒內退出,這不會發生。 –

+0

我明白了。嘗試getc並設置tty選項,如下所示:https://perldoc.perl.org/functions/getc.html – yacc

回答

3

當後臺進程嘗試終端輸入時,會發送信號SIGTTIN,該信號的默認動作爲「停止」 - 即進程已暫停,與接收到SIGSTOP時相同。由於它停止了,它沒有機會處理它的警報,退出或者做其他任何事情。

因此,您將要設置SIGTTIN處理程序來覆蓋該默認停止行爲。

你可以做的最簡單的事情是local $SIG{TTIN} = 'IGNORE';這會導致信號被忽略。然後STDIN的讀取會立即失敗(返回undef,$!設置爲EIO),並且在代碼中會出現「input is undefined」情況。

您也可以設置local $SIG{TTIN} = sub { die "process is backgrounded" };這可以讓您更清楚地區分這種情況。

或者你可以設置一個聰明的信號處理程序和重試讀取,以便在用戶決定後臺和重新附加超時過期之前,他們仍然能夠提供輸入,但我離開那取決於你。

+0

讀這個我想念我們一直在Unix上的日子。 :) – yacc

+0

感謝您的詳細解釋。 '本地$ SIG {TTIN} =子{死「過程是後臺」};'工作:) –

+1

@yacc我_am_所有時間在unix :) – zdim