Захват Perl Ctrl-C (sigint) в bash - PullRequest
       50

Захват Perl Ctrl-C (sigint) в bash

1 голос
/ 22 сентября 2011

Я читаю Как мы собираем CTRL ^ C - Perl Monks , но я не могу получить нужную информацию, чтобы помочь с моей проблемой.

Дело в том, что у меня есть бесконечный цикл и «многострочная» распечатка на терминал ( Я знаю, мне будет сказано использовать ncurses вместо этого - но для коротких сценариев мне удобнее написание связки printf s ). Я бы хотел перехватить Ctrl-C таким образом, чтобы скрипт завершал работу только после завершения многострочной распечатки.

Сценарий (Ubuntu Linux 11.04):

#!/usr/bin/env perl
use strict;
use warnings;

use Time::HiRes;

binmode(STDIN);   # just in case
binmode(STDOUT);   # just in case


# to properly capture Ctrl-C - so we have all lines printed out
# unfortunately, none of this works:
my $toexit = 0;
$SIG{'INT'} = sub {print "EEEEE";  $toexit=1; };
#~ $SIG{INT} = sub {print "EEEEE";  $toexit=1; };
#~ sub REAPER { # http://www.perlmonks.org/?node_id=436492
        #~ my $waitedpid = wait;
        #~ # loathe sysV: it makes us not only reinstate
        #~ # the handler, but place it after the wait
        #~ $SIG{CHLD} = \&REAPER;
        #~ print "OOOOO";
    #~ }
#~ $SIG{CHLD} = \&REAPER;
#~ $SIG{'INT'} = 'IGNORE';



# main

# /21336/kak-ya-mogu-proverit-stdin-bez-blokirovki-v-perl
use IO::Select;
my $fsin = IO::Select->new();
$fsin->add(\*STDIN);


my ($cnt, $string);
$cnt=0;
$string = "";

while (1) {
  $string = ""; # also, re-initialize
  if ($fsin->can_read(0)) { # 0 timeout
    $string = <STDIN>;
  }
  $cnt += length($string);

  printf "cnt: %10d\n", $cnt;
  printf "cntA: %10d\n", $cnt+1;
  printf "cntB: %10d\n", $cnt+2;
  print "\033[3A"; # in bash - go three lines up
  print "\033[1;35m"; # in bash - add some color
  if ($toexit) { die "Exiting\n" ; } ;
}

Теперь, если я запускаю это и нажимаю Ctrl-C, я либо получаю что-то вроде этого (примечание , _ указывает положение оконечного курсора после завершения сценария ):

MYPROMPT$ ./test.pl
cnEEEEEcnt:          0
MYPROMPT$ _
cntB:          2
Exiting

или

MYPROMPT$ ./test.pl
cncnt:          0
MYPROMPT$ _
cntB:          2
Exiting

... однако я бы хотел получить:

MYPROMPT$ ./test.pl
cncnt:          0
cntA:          1
cntB:          2
Exiting
MYPROMPT$ _

Очевидно, что обработчики запущены - но не совсем в том времени (или порядке), которого я ожидаю. Может кто-нибудь уточнить, как мне это исправить, чтобы я получил желаемый результат?

Большое спасибо заранее за любые ответы, Ура!

1 Ответ

1 голос
/ 22 сентября 2011

Хммм ... кажется, решение оказалось проще, чем я думал :) По сути, проверка на "ловушку выхода" должна выполняться после того, как строки напечатаны - но до того, как будут напечатаны символы "идти на три строки вверх";то есть этот раздел должен иметь вид:

  printf "cnt: %10d\n", $cnt;
  printf "cntA: %10d\n", $cnt+1;
  printf "cntB: %10d\n", $cnt+2;
  if ($toexit) { die "Exiting\n" ; } ;
  print "\033[3A"; # in bash - go three lines up
  print "\033[1;35m"; # in bash - add some color

... и затем вывод при Ctrl-C выглядит следующим образом:

MYPROMPT$ ./test.pl 
cnt:          0
^CcntA:          1
cntB:          2
Exiting
MYPROMPT$  _

Что ж, надеюсь, это кому-то поможет,
Ура!

...