System.gc() is async, do not attempt to invoke it and retry sysopen#2768
System.gc() is async, do not attempt to invoke it and retry sysopen#2768headius merged 2 commits intojruby:masterfrom
Conversation
|
When I did the port of this and other similar code, I left this in mostly to keep the code consistent with MRI until I decided how to refactor it. I agree that this code is not effective in JRuby and it should be removed. Your patch is mostly ok, but it leaves a nested if (fd == null) check in place. If you'd like to audit other places we call System.gc, they could probably benefit from similar treatment. |
…s it will always fail
|
Fixed the nested (fd == null) check, thanks. Jruby doesn't seem to have the other EMFILE guards around other descriptor generating calls like Dir or Socket. I do see a few invocations in places such as AllocatedNativeMemoryIO. I'm not entirely clear on whether that invocation is effective, but given the context it probably doesn't hurt since it tests and throws. |
|
|
IO objects abandoned while still open will call
close()in their finalizer. Taking advantage of this behavior, MRI guards every fd allocating syscall retrying the syscall after running the GC if EMFILE/ENFILE are encountered:https://github.com/ruby/ruby/blob/trunk/io.c#L5449-L5454
https://github.com/ruby/ruby/blob/trunk/dir.c#L485-L489
https://github.com/ruby/ruby/blob/trunk/ext/socket/socket.c#L243-L246
This is possible in MRI because
rb_gc()blocks while the GC runs, guaranteeing that finalizers will have been invoked before the syscall is retried.System.gc()doesn't block, however, so this approach on the JVM will always fail.The guards in jruby are also incomplete. As best I can tell they only exist around sysopen call, but don't exist around other descriptor allocating calls (directories, sockets, etc)
It seems to me that jruby could do one of several things:
I don't know of a good way to emulate the behavior of MRI in this case, unfortunately.