JRuby

The behaviour of File.flock is not same with C Ruby

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: JRuby 1.0.0
  • Fix Version/s: JRuby 1.1RC2
  • Component/s: Core Classes/Modules
  • Labels:
    None
  • Environment:
    Mac OS, windows, jruby 1.0, JDK1.5
  • Number of attachments :
    2

Description

created a file "t.txt"
ruby code: File.new('t.txt').flock(File::LOCK_EX)

for C Ruby, it works well.
it will throw java.nio.channels.NonWritableChannelException on JRuby.

the following is the full stacktrace I got:
----start---
C:\Documents and Settings\xli\Desktop\New Folder\jruby-1.0>bin\jruby -e "p File.new('t.txt').flock(F
ile::LOCK_EX)"
FileChannelImpl.java :773:in `sun.nio.ch.FileChannelImpl.lock': java.nio.channels.NonWritableChannelE
xception: null (NativeException)
from FileChannel.java:865:in `java.nio.channels.FileChannel.lock'
from RubyFile.java :314:in `org.jruby.RubyFile.flock'
from null:-1:in `org.jruby.RubyFileInvokerflock1.call'
from FastInvocationCallback.java:49:in `org.jruby.runtime.callback.FastInvocationCallback.ex
ecute'
from SimpleCallbackMethod.java:81:in `org.jruby.internal.runtime.methods.SimpleCallbackMetho
d.call'
from EvaluationState.java:568:in `org.jruby.evaluator.EvaluationState.callNode'
from EvaluationState.java:207:in `org.jruby.evaluator.EvaluationState.evalInternal'
from EvaluationState.java:2190:in `org.jruby.evaluator.EvaluationState.setupArgs'
... 8 levels...
from Main.java:173:in `org.jruby.Main.runInterpreter'
from Main.java:120:in `org.jruby.Main.run'
from Main.java:95:in `org.jruby.Main.main'
Complete Java stackTrace
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.lock(FileChannelImpl.java:773)
at java.nio.channels.FileChannel.lock(FileChannel.java:865)
at org.jruby.RubyFile.flock(RubyFile.java:314)
at org.jruby.RubyFileInvokerflock1.call (Unknown Source)
at org.jruby.runtime.callback.FastInvocationCallback.execute(FastInvocationCallback.java:49)

at org.jruby.internal.runtime.methods.SimpleCallbackMethod.call(SimpleCallbackMethod.java :81
)
at org.jruby.evaluator.EvaluationState.callNode(EvaluationState.java:568)
at org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:207)
at org.jruby.evaluator.EvaluationState.setupArgs (EvaluationState.java:2190)
at org.jruby.evaluator.EvaluationState.fCallNode(EvaluationState.java:1007)
at org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:253)
at org.jruby.evaluator.EvaluationState.rootNode (EvaluationState.java:1609)
at org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:356)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:164)
at org.jruby.Ruby.eval (Ruby.java:287)
at org.jruby.Ruby.compileOrFallbackAndRun(Ruby.java:315)
at org.jruby.Main.runInterpreter(Main.java:228)
at org.jruby.Main.runInterpreter(Main.java:173)
at org.jruby.Main.run (Main.java:120)
at org.jruby.Main.main(Main.java:95)
--end--

I took a look at JRuby code org.jruby.RubyFile and org.jruby.util.IOHandler,
and there is only one IOHandler sub class(IOHandlerSeekable) I found implements getChannel method for RubyFile to use it to lock file.

IOHandlerSeekable will create a RandomAccessFile and get FileChannel from it in the method getChannel.
And it pass file open mode to initialize RandomAccessFile object.

FileChannel will throw NonWritableChannelException when it trys to lock a file with shared is false and it was not opened for writing.

so, the code "File.new("t.txt", "w+").flock(File::LOCK_EX)" works well.

  1. flock-patch.diff
    13/Feb/08 8:03 AM
    0.6 kB
    Kaoru Kobo
  2. tc_test.rb
    17/Jul/07 7:32 PM
    0.6 kB
    Nicolas Modrzyk

Activity

Hide
Nicolas Modrzyk added a comment -

this is the test associated with the bug.
and the patch to fix it.

Running the full test suite on jruby worked okay with the patch, and indeed if ruby is waiting to have the file opened read/write by default, we might as well do it in jruby.

Show
Nicolas Modrzyk added a comment - this is the test associated with the bug. and the patch to fix it. Running the full test suite on jruby worked okay with the patch, and indeed if ruby is waiting to have the file opened read/write by default, we might as well do it in jruby.
Hide
Charles Oliver Nutter added a comment -

The given patch sets File::new to be read/write by default; however, that's not the correct behavior for Ruby. We need to determine how Ruby locks files only opened for read; perhaps it's locking them shared? Can someone look into this?

Show
Charles Oliver Nutter added a comment - The given patch sets File::new to be read/write by default; however, that's not the correct behavior for Ruby. We need to determine how Ruby locks files only opened for read; perhaps it's locking them shared? Can someone look into this?
Hide
Charles Oliver Nutter added a comment -

We need some footwork on this one or it will move to 1.0.3...

Show
Charles Oliver Nutter added a comment - We need some footwork on this one or it will move to 1.0.3...
Hide
Charles Oliver Nutter added a comment -

Bumped off 1.0.2.

Show
Charles Oliver Nutter added a comment - Bumped off 1.0.2.
Hide
Kaoru Kobo added a comment -

In file.c of CRuby(1.8.6-p111), it just calls flock with LOCK_EX.
It may Java's limitation.
How about calling lock with shared argument false for read-only channel even if LOCK_EX is given?
I think it does not cause problem so much.
(Is there a case to lock a file exclusively without updating it?)

Show
Kaoru Kobo added a comment - In file.c of CRuby(1.8.6-p111), it just calls flock with LOCK_EX. It may Java's limitation. How about calling lock with shared argument false for read-only channel even if LOCK_EX is given? I think it does not cause problem so much. (Is there a case to lock a file exclusively without updating it?)
Hide
Kaoru Kobo added a comment -

> with shared argument false
with shared argument true

Show
Kaoru Kobo added a comment - > with shared argument false with shared argument true
Hide
Vladimir Sizikov added a comment -

Indeed, the exclusive lock is in many cases even referred to as "write lock", so the proposed patch makes perfect sense. I wish FileChannel wouldn't enforce these read/write cases with maningless exception, in a manner like libc does.

Show
Vladimir Sizikov added a comment - Indeed, the exclusive lock is in many cases even referred to as "write lock", so the proposed patch makes perfect sense. I wish FileChannel wouldn't enforce these read/write cases with maningless exception, in a manner like libc does.
Hide
Vladimir Sizikov added a comment -

The issue has been resolved in rev. r5930 on trunk.
(Patch by Kaoru Shirai, with modifications and regression test).

This also eliminates rubyspec hard crash, since some recent rubyspecs added flock tests that trigger the exception.

Show
Vladimir Sizikov added a comment - The issue has been resolved in rev. r5930 on trunk. (Patch by Kaoru Shirai, with modifications and regression test). This also eliminates rubyspec hard crash, since some recent rubyspecs added flock tests that trigger the exception.

People

Vote (0)
Watch (3)

Dates

  • Created:
    Updated:
    Resolved: