Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a new file descriptor from stdout with fcntl fails in files

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

like image 826
Kaiepi Avatar asked Mar 30 '18 12:03

Kaiepi


People also ask

Is stdout a file descriptor?

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).

Is 0 a valid file descriptor?

0 is a valid file descriptor, but it usually refers to stdin.

What is the file descriptor in linux?

A file descriptor is an unsigned integer used by a process to identify an open file.


1 Answers

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);
}
like image 56
Kaiepi Avatar answered Oct 18 '22 21:10

Kaiepi