Создание нового файлового дескриптора из 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);
}