Issue Details (XML | Word | Printable)

Key: JRUBY-1214
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Vladimir Sizikov
Reporter: Li Xiao
Votes: 0
Watchers: 3
Operations

If you were logged in you would be able to see more operations.
JRuby

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

Created: 16/Jul/07 08:20 PM   Updated: 18/Sep/08 10:34 PM   Resolved: 14/Feb/08 10:07 AM
Return to search
Component/s: Core Classes/Modules
Affects Version/s: JRuby 1.0.0
Fix Version/s: JRuby 1.1RC2

Time Tracking:
Not Specified

File Attachments: 1. File flock-patch.diff (0.6 kB)
2. File tc_test.rb (0.6 kB)

Environment: Mac OS, windows, jruby 1.0, JDK1.5


 Description  « Hide

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.



Nicolas Modrzyk added a comment - 17/Jul/07 07:32 PM

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.


Charles Oliver Nutter added a comment - 21/Oct/07 11:04 PM

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?


Charles Oliver Nutter added a comment - 26/Oct/07 11:09 PM

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


Charles Oliver Nutter added a comment - 30/Oct/07 02:15 AM

Bumped off 1.0.2.


Kaoru Shirai added a comment - 13/Feb/08 07:25 AM

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


Kaoru Shirai added a comment - 13/Feb/08 07:25 AM

> with shared argument false
with shared argument true


Vladimir Sizikov added a comment - 14/Feb/08 10:04 AM

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.


Vladimir Sizikov added a comment - 14/Feb/08 10:07 AM

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.