Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

duplicate stat() system calls on file tests #2584

Open
bugfood opened this issue Jan 5, 2019 · 4 comments
Open

duplicate stat() system calls on file tests #2584

bugfood opened this issue Jan 5, 2019 · 4 comments
Labels

Comments

@bugfood
Copy link

bugfood commented Jan 5, 2019

The Problem

IO::Path methods to test file metadata (.l, .f, etc.) issue two stat()/lstat() system calls when one will suffice.

Expected Behavior

A single "foo".IO.l call will result in a single lstat().
A single "foo".IO.f call will result in a single stat().

Actual Behavior

A single "foo".IO.l call results in two calls to lstat().
A single "foo".IO.f call result in two calls to stat().

Steps to Reproduce

Prepare:

$ cd /tmp
$ touch foo

Perl 6 test, unexpected behavior:

$ strace -f -e trace=stat,lstat perl6 -e 'say "hi" if "foo".IO.l' 2>&1 | grep foo
[pid 10876] lstat("/tmp/foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
[pid 10876] lstat("/tmp/foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
$ strace -f -e trace=stat,lstat perl6 -e 'say "hi" if "foo".IO.f' 2>&1 | grep foo
[pid 10881] stat("/tmp/foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
[pid 10881] stat("/tmp/foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0

Perl 5 test, expected behavior:

$ strace -f -e trace=stat,lstat perl -e 'print "hi\n" if -l "foo"' 2>&1 | grep foo
lstat("foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
$ strace -f -e trace=stat,lstat perl -e 'print "hi\n" if -f "foo"' 2>&1 | grep foo
stat("foo", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0

One possible hint as to why this happens is that there is only a single call when the file is missing. It appears as if perl 6 is issuing one stat() to determine if the file exists and then another stat() to gather data for the user-requested test.

$ rm -f foo
$ strace -f -e trace=stat,lstat perl6 -e 'say "hi" if "foo".IO.f' 2>&1 | grep foo
[pid 10911] stat("/tmp/foo", 0x7ffd7d0e9810) = -1 ENOENT (No such file or directory)

Environment

  • Operating system:
$ cat /etc/debian_version 
buster/sid
  • Compiler version (perl6 -v):
$ perl6 -v
This is Rakudo version 2018.11 built on MoarVM version 2018.11
implementing Perl 6.d.

Thanks,
Corey

@cuonglm
Copy link
Contributor

cuonglm commented Jan 5, 2019

You can't do it, at least with current version of MoarVM https://github.com/MoarVM/MoarVM/blob/a5dd7652d4ca0ff67aac5c7809958e030abcbacf/src/io/fileops.c#L16

Basically, file stat is not expose directly to nqp side, you have to perform multiple nqp::stat calls to get the file information, mostly 2 (.l, .e...), .w even use 3.

@zoffixznet
Copy link
Contributor

zoffixznet commented Jan 5, 2019

This was the never-implemented extra part of the IO Grant:
https://github.com/rakudo/rakudo/blob/master/docs/archive/2017-IO-Grant--Action-Plan.md#iopath-routines-that-involve-a-stat-call-issue-for-discussion

With a discussion that led to the proposal for nqp::statmulti op, to be used by methods that need more than one piece of stat info: zoffixznet/IOwesomeness#4 (also IRC discussion)

@bugfood
Copy link
Author

bugfood commented Jan 6, 2019

Thanks for the clarifying information; I was not able to find the earlier discussions when I looked.

If the ideas are covered elsewhere, then I would understand if you close this bug as a duplicate.

Thanks,
Corey

@zoffixznet
Copy link
Contributor

then I would understand if you close this bug as a duplicate.

I think it's good to have this ticket open. I'm not aware of any other ticket on this matter in the rakudo's repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants