0

少し前に、モジュールで使用するときに$ SIG {WINCH}の問題を$SIG{WINCH}使用していた2つのモジュールをロードしたため、問題が発生しました。今、私はこのケースを再構築しようとしましたが、今回はサブルーチン内の1つのモジュールに入れました。$SIG{WINCH} $SIG{WINCH}

use warnings;
use strict;
package My_Package;
use Exporter 'import';
our @EXPORT = qw(choose);

sub choose {
    # ...
    my $size_changed;
    local $SIG{WINCH} = sub { $size_changed = 1; }; # edit: added "local"
    while ( 1 ) {
        my $c = getch();
        if ( $size_changed ) {
            write_screen();
            $size_changed = 0;
            next;
        }
        # ...
    }
}

これで、機能しているように見えます。このようにローカライズした場合$SIG{WINCH}、または再構築時に何かを忘れた場合、保存できますか?

4

1 に答える 1

1

これが機能するのは、コードwhileがシグナル ハンドラーを設定した直後にループに入り、他のコードが実行されない (または新しいハンドラーが設定されない) ためです。while ループが終了すると、ハンドラの設定が解除され、古いハンドラが のおかげで自動的に復元されますlocal

より回復力のあるコードについては、既存のシグナル ハンドラーが存在するかどうかを確認し、それを呼び出します。そうしないと、SIGWINCH ハンドラーを持つ他のモジュールが壊れてしまいます。例えば

my $orig_sigwinch = $SIG{WINCH};
local $SIG{WINCH} = sub {
    $orig_sigwinch->() if $orig_sigwinch && ref $orig_sigwinch eq 'CODE';
    $size_changed = 1;
}

$orig_sigwinchこれは、 がコード参照ではなく関数名である場合を考慮していないことに注意してください。

于 2012-08-11T09:45:43.607 に答える