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

File#mtime does not behave like it does in MRI in respect to renamed and deleted files on POSIX #5073

Closed
Taywee opened this Issue Mar 1, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@Taywee

Taywee commented Mar 1, 2018

Environment

  • jruby 9.1.16.0 (2.3.3) 2018-02-21 8f3f95a OpenJDK 64-Bit Server VM 25.151-b12 on 1.8.0_151-b12 +jit [linux-x86_64]
  • Linux nyarlathotep 4.14.11-gentoo-r2 #2 SMP Wed Feb 28 17:37:50 MST 2018 x86_64 Intel(R) Core(TM) i5-3570K CPU @ 3.40GHz GenuineIntel GNU/Linux

Expected Behavior

File#mtime doesn't return the same data for File#stat#mtime when the file has been renamed or deleted since the filehandle was opened (if the file has been removed, it throws an exception; if the file has been renamed, it silently gets the wrong data). MRI gets this data from the open filehandle and therefore gets the correct mtime. There are probably other methods on File that are shortcuts for stat that have this same issue. #size appears to have the correct behavior, but #ctime and #atime do not.

Here's an example program that works on MRI (printing "true" twice) but crashes in Jruby:

#!/usr/bin/env ruby

require 'tmpdir'
require 'pathname'
require 'fileutils'

Dir.mktmpdir do |dir|
  dir = Pathname.new dir
  filename = dir + 'foo'
  File.open(filename, 'w') {|f| f.puts('foo')}
  file = File.open filename
  p file.stat.mtime == file.mtime
  File.rename(filename, dir + 'bar')
  p file.stat.mtime == file.mtime
end

In MRI

true
true

Note that in MRI on Windows, this fails as well, due to Windows files being locked for deletion and renaming when they are open for reading, so it throws a permission denied error. This version works in MRI on Windows:

Dir.mktmpdir do |dir|
  dir = Pathname.new dir
  filename = dir + 'foo'
  File.open(filename, 'w') {|f| f.puts('foo')}
  File.open(filename, File::BINARY | File::SHARE_DELETE) do |file|
    p file.stat.mtime == file.mtime
    File.delete(filename)
    p file.stat.mtime == file.mtime
  end
end

Actual Behavior

true
Errno::ENOENT: No such file or directory - /tmp/d20180301-17838-1pibcq4/foo
               mtime at org/jruby/RubyFile.java:440
  block in ./test.rb at ./test.rb:14
                open at org/jruby/RubyIO.java:1171
  block in ./test.rb at ./test.rb:11
            mktmpdir at /home/taylor/.rbenv/versions/jruby-9.1.16.0/lib/ruby/stdlib/tmpdir.rb:89
              <main> at ./test.rb:7
@headius

This comment has been minimized.

Member

headius commented Mar 19, 2018

Confirmed. I believe I have the fix.

headius added a commit that referenced this issue Mar 19, 2018

@headius headius added this to the JRuby 9.1.17.0 milestone Mar 19, 2018

@headius

This comment has been minimized.

Member

headius commented Mar 19, 2018

This is fixed for 9.1.17. Perhaps you could add a spec for this to https://github.com/ruby/spec?

@headius headius closed this Mar 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment