I have a simple test file that looks like this:
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);
The file descriptor gets returned is -1, which is not what I want. But when I run the same code in a REPL, I get what I'm looking for:
> 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
Why doesn't fcntl
create a new file descriptor in the file like it does in the REPL?
Edit: I'm running OpenBSD 6.2, Rakudo 2018.02
Stdin, stdout, and stderr On a Unix-like operating system, the first three file descriptors, by default, are STDIN (standard input), STDOUT (standard output), and STDERR (standard error).
0 is a valid file descriptor, but it usually refers to stdin.
A file descriptor is an unsigned integer used by a process to identify an open file.
When using the F_DUPFD flag with fcntl (which was 0), OpenBSD requires that the status flags the original file descriptor had be passed on to the new one as well. So this will work:
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With