-
-
Notifications
You must be signed in to change notification settings - Fork 925
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
Can't use require_relative
with a path beginning with lib
in a jar...on Linux
#4145
Comments
@presidentbeef can not reproduce on OSX with jruby-complete-9.1.5.0 using the repository you mentioned. I see
well the missing stylesheet is definitely using an uri-like path which will not find anything. looks like the StyleManager thinks it is a path on the filesystem. what is your |
@mkristian as noted above, this issue does not occur on OS X. |
@presidentbeef oh -sorry. let me try it on my linux VM then |
@mkristian I think you are right - this is something to do with my environment. I tried it on a completely different Linux machine and it loaded just fine. However - why would In any case, here is my crufty
|
@presidentbeef as I can not reproduce it and the env did not show anything obvious, I just can point you to the require_relative method: https://github.com/jruby/jruby/blob/master/core/src/main/ruby/jruby/kernel/kernel.rb#L3 there is some conversion going on like |
Thanks - in some ways it is a relief to know this isn't a general problem :) |
@presidentbeef Perhaps on that one Linux environment you have a Perhaps you can play around with our |
I am continuing to look into this because things are getting weird. First of all, now I can't reproduce it with the jrubyfx-9k-jar-problems repo either. Which is pretty strange. Secondly, I thought it was Thirdly, I didn't realize this isn't a Sorry for the confusion, I've been fighting this for a few days and my brain hurts a little. |
I have a much simpler repro repo: https://github.com/presidentbeef/jruby-realpath-error It comes down to behavior of
However, this only happens on one machine. The error goes away if I rename Still scratching my head about it. |
I imagine the renaming changes behavior because somewhere along the line it doesn't see a real system path anymore, so it goes back to searching the classloader. Thanks for the reproduction! That will definitely help us sort out what's happening here. |
@mkristian I don't suppose you have a fix up your sleeve for 9.1.6.0? Otherwise we'll have to punt. |
Too late! |
I'm still unclear what's happening here. Do you have any updates @presidentbeef? I've retargeted for 9.2 but this is in danger of slipping forever. |
Considering the repro has been condensed down to I will do my best to take a look and see if I can figure out where/why things are going wrong. |
I have located what I believe to be the smoking gun. In my example (and in the real app), the If I am tracing the code right, this is the code that is execuded in expandPathInternal. Note the call to NOW IT GETS INTERESTING On Mageia Linux:
On Mac OSX and Ubuntu Linux:
The version of Java does not seem to matter (same results with OpenJDK and Oracle Java SE). On Mageia I have:
On Ubuntu:
I can reproduce the issue in pure Java. So I don't think this is a JRuby problem at all. |
I played around with this for a minute and think I have it. It looks like java seems to resolve symbolic links when doing import java.io.File;
class Test {
public static void main(String[] args) throws Exception {
File foo = new File("/tmp/foo.rb");
System.out.println(foo.getCanonicalPath());
}
}
Patricks-MacBook-Pro:Downloads ptoomey3$ java Test
/private/tmp/foo.rb |
wow - great findings. so |
Holy cow @ptoomey3! I thought this was a lost cause 😀 Amazing work. |
@ptoomey3 Yeah great investigation! So I think we just need to stop calling path canonicalization methods on all in-jar or in-classpath paths, eh? |
I am testing the following patch: diff --git a/core/src/main/java/org/jruby/RubyFile.java b/core/src/main/java/org/jruby/RubyFile.java
index 9a861ab..11c0057 100644
--- a/core/src/main/java/org/jruby/RubyFile.java
+++ b/core/src/main/java/org/jruby/RubyFile.java
@@ -1638,32 +1638,39 @@ public class RubyFile extends RubyIO implements EncodingCapable {
int index = relativePath.indexOf("!/");
postFix = relativePath.substring(index);
relativePath = relativePath.substring(0, index);
- }
- else if (protocol.find()) {
+ } else if (protocol.find()) {
preFix = protocol.group();
int offset = protocol.end();
String extra = "";
int index = relativePath.indexOf("file://");
+ boolean classloaderURI = preFix.equals("uri:classloader:") || preFix.equals("classpath:");
+
if (index >= 0) {
index += 7; // "file://".length == 7
// chck if its "file:///"
if (relativePath.length() > index && relativePath.charAt(index) == '/') {
offset += 2; extra = "//";
- }
- else {
+ } else {
offset += 1; extra = "/";
}
+ } else {
+ if (classloaderURI && relativePath.startsWith("//", offset)) {
+ // on Windows "uri:classloader://home" ends up as "//home" - trying a network drive!
+ offset += 1; // skip one '/'
+ }
}
- else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
- && relativePath.startsWith("//", offset) ) {
- // on Windows "uri:classloader://home" ends up as "//home" - trying a network drive!
- offset += 1; // skip one '/'
+
+ relativePath = relativePath.substring(offset);
+
+ if (!classloaderURI) {
+ relativePath = canonicalizePath(relativePath);
}
- relativePath = canonicalizePath(relativePath.substring(offset));
+
if (Platform.IS_WINDOWS && !preFix.contains("file:") && startsWithDriveLetterOnWindows(relativePath)) {
// this is basically for classpath:/ and uri:classloader:/
relativePath = relativePath.substring(2).replace('\\', '/');
}
+
return concatStrings(runtime, preFix, extra, relativePath, enc);
}
This skips the canonicalization for any classloader URIs:
|
Ok, I realized with my patch that we do expect canonicalization of classpath URIs to expand filesystem relative paths like "/lib/../foo". I have modified my patch to canonicalize classpath URIs using a bogus path prefix that will never resolve to anything on the actual filesystem. Seems to be working ok. |
This prevents in-classloader paths from expanding using real filesystem paths that may resolve symlinks. Fixes jruby#4145.
Pushed a PR, we'll see how it feels. |
has been attempted at cbf9a7d ... using a fake root path, however on Windows /SMT expands as C:\SMT added '__' at the end so its more obvious if this is slightly off again closes jruby#4630 (also jruby#4645)
help classpath: canonicalization on Windows to fully resolve #4145
Environment
Provide at least:
jruby 9.1.5.0 (2.3.1) 2016-09-07 036ce39 Java HotSpot(TM) 64-Bit Server VM 25.65-b01 on 1.8.0_65-b17 +jit [linux-x86_64]
Linux bigblue 4.4.16-desktop-1.mga5 #1 SMP Tue Jul 26 09:23:40 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Other relevant info you may wish to add:
Just
bundler
jrubyfx
Expected Behavior
Load any file in a jar using
require_relative
The jrubyfx-9k-jar-problems repo can be re-purposed for this bug, as a follow up to #4000
Actual Behavior
The actual behavior is that
require_relative "lib/brakeman_pro"
can't find the file. But if you just move the file tolib2/brakeman_pro.rb
and require that, it works!I build the jar like this:
Then I run
I have tried with JRuby 9.1.3.0, 9.1.4.0, and 9.1.5.0. They all show the same behavior.
A jar built on OSX works on OSX but shows the same error if I run that jar on Linux.
After spending several hours on this, I realized the first
require_relative
in the bootstrap file works just fine, which baffled me. So I tested requiring other files in different directories and the root directory. They worked just fine. An unsettling realization came over me. I changed move the file tolib2
, adjusted therequire_relative
call and...it worked. 😱The text was updated successfully, but these errors were encountered: