Создание нового файлового дескриптора из stdout с помощью fcntl завершается неудачно в файлах

У меня есть простой тестовый файл, который выглядит так:

use v6.c;
use NativeCall;

sub fcntl(int32, int32 --> int32) is native { * }
sub close(int32 --> int32) is native { * }

my $fd := fcntl($*OUT.native-descriptor, 0);
say $fd;
close($fd);

Возвращаемый дескриптор файла равен -1, а это не то, что я хочу. Но когда я запускаю тот же код в REPL, я получаю то, что ищу:

> use NativeCall
Nil
> sub fcntl(int32, int32 --> int32) is native { * }
sub fcntl (int32 $, int32 $ --> int32) { #`(Sub+{Callable[int32]}+{NativeCall::Native[Sub+{Callable[int32]},Str]}|17126514527616) ... }
> sub close(int32 --> int32) is native { * }
sub close (int32 $ --> int32) { #`(Sub+{Callable[int32]}+{NativeCall::Native[Sub+{Callable[int32]},Str]}|17126514527904) ... }
> my $fd := fcntl($*OUT.native-descriptor, 0)
15
> say $fd
15
> close($fd)
0

Почему не fcntl создать новый дескриптор файла в файле, как это делает в REPL?

Изменить: я использую OpenBSD 6.2, Rakudo 2018.02

1 ответ

Решение

При использовании флага F_DUPFD с fcntl (который был равен 0), OpenBSD требует, чтобы флаги состояния, которые исходный дескриптор файла также передавал новому. Так что это будет работать:

use v6.c;
use NativeCall;

constant F_DUPFD = 0;
constant F_GETFD = 1;

sub fcntl(int32, int32, int32 --> int32) is native { * }
sub close(int32 --> int32) is native { * }

sub MAIN() {
    my $out-fd := $*OUT.native-descriptor;
    my $flags  := fcntl($out-fd, F_GETFD, 0);
    my $fd     := fcntl($out-fd, F_DUPFD, $flags);
    say $fd; # 15
    close($fd);
}
Другие вопросы по тегам