Почему слой ввода-вывода utf8 удаляется при порождении процесса демона? - PullRequest
2 голосов
/ 20 апреля 2019

Следующий код работает как положено:

use feature qw(say);
use strict;
use warnings;
use open qw/:std IN :encoding(utf-8) OUT :utf8/; 

say  join ' ', (PerlIO::get_layers(\*STDOUT));
my $pid = fork();
die "fork() failed: $!" unless defined $pid;
if ($pid == 0) {
    say  join ' ', (PerlIO::get_layers(\*STDOUT));
}

выход

unix perlio utf8
unix perlio utf8

Но если я использую процесс-демон вместо обычного форка:

use feature qw(say);
use strict;
use warnings;
use open qw/:std IN :encoding(utf-8) OUT :utf8/; 
use Cwd qw(getcwd);
use Proc::Daemon;

my $work_dir = getcwd;    
my $daemon = Proc::Daemon->new(
    work_dir     => $work_dir,
    child_STDOUT => 'stdout.txt',
    child_STDERR => 'stderr.txt',
    pid_file     => 'pid.txt',
);
my $pid = $daemon->Init();
if ( $pid == 0 ) {
    say  join ' ', (PerlIO::get_layers(\*STDOUT));
}

Вывод в файл stdout.txt:

unix perlio

поэтому слой utf8 IO был удален.

1 Ответ

2 голосов
/ 20 апреля 2019

Рассмотрим этот пример:

Foo.pm:

package Foo;
use warnings;
use strict;
sub test {
  close STDIN;
  open \*STDIN, "<", "/dev/null";
}
1;

test.pl:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw/say/;
use open qw/:std IN :encoding(UTF-8) OUT :encoding(UTF-8)/;
use lib qw/./;
use Foo;

$, = ' ';
say "Original STDIN:", PerlIO::get_layers(\*STDIN);
close STDIN;
open \*STDIN, "<", "/dev/null";
say "Reopened STDIN:", PerlIO::get_layers(\*STDIN);
Foo::test();
say "Reopened STDIN in different package:", PerlIO::get_layers(\*STDIN);

Результаты:

$ perl test.pl
Original STDIN: unix perlio encoding(utf-8-strict) utf8
Reopened STDIN: unix perlio encoding(utf-8-strict) utf8
Reopened STDIN in different package: unix perlio

Похоже, use open похож на другие прагмы и относится только к файлу, который в нем находится. Поэтому, когда Proc::Daemon закрывает стандартный ввод, вывод и ошибку и снова открывает их, он, естественно, не видит дополнительные слои.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...