Skip to content
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

reporting a better error when tmp doesn't work for temporary executables #5900

Closed
jacaetevha opened this issue Oct 1, 2019 · 7 comments
Closed
Milestone

Comments

@jacaetevha
Copy link

@jacaetevha jacaetevha commented Oct 1, 2019

Environment

  • JRuby version: 9.2.8.0
  • OS: Linux vpna-dev-tmc039.ad-dev.issgovernance.com 3.10.0-1062.1.1.el7.x86_64 #1 SMP Tue Aug 13 18:39:59 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Expected Behavior

When packing up a JRuby application as an executable JAR via warble, the app may crash if the temp directory (/tmp by default on most *nix systems) is mounted as read-only or noexec. A useful error message that instructs the user to set a temp directory to some user-space would be helpful. E.g. /tmp is mounted as read-only or noexec. Some native extensions may not work properly. Try setting the "java.io.tmpdir" variable to a directory that is writeable and executable by your process, if you run into errors with native extensions.

Example Application

example/bin/example

require 'irb'
IRB.start(__FILE__)

config/warble.rb

Warbler::Config.new do |config|
  config.features = %w(gemjar)
  config.includes = FileList["script.rb"]
  config.jar_extension = "jar"
  config.autodeploy_dir = "dist/"
  config.bytecode_version = "1.8"
end
warble
java -jar example.jar # throws an error if /tmp is noexec or read-only

Actual Behavior

When /tmp is mounted as noexec an error similar to the following is written to the console:

NotImplementedError: fstat unimplemented unsupported or native support failed to load; see https://github.com/jruby/jruby/wiki/Native-Libraries
  initialize at org/jruby/RubyIO.java:1015
        open at org/jruby/RubyIO.java:1156
  initialize at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/input-method.rb:141
  initialize at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/context.rb:70
  initialize at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb.rb:410
       start at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb.rb:381
      <main> at dbconsole/bin/dbconsole:10
        load at org/jruby/RubyKernel.java:1022
      <main> at uri:classloader:/META-INF/main.rb:1
     require at org/jruby/RubyKernel.java:987
      <main> at uri:classloader:/META-INF/main.rb:1
      <main> at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1
ERROR: org.jruby.embed.EvalFailedException: (NotImplementedError) fstat unimplemented unsupported or native support failed to load; see https://github.com/jruby/jruby/wiki/Native-Libraries

If you pass -Djruby.native.verbose=true to java, you'll get more information that indicates that /tmp may be the problem (e.g. this gist).

@headius
Copy link
Member

@headius headius commented Oct 1, 2019

Read-only bug is at #1302. A suggestion there is that we could pick a different location, either by default or only when we detect that the default tmp location won't work.

However, it's not clear how we can tell tmp won't work unless we try to make it work. As it is, we are not the ones unpacking the native library; that is done by either jnr-ffi or jffi (I don't recall).

So we definitely need a better error or warning when tmp is unusable, and ideally a simple way to fall back to some other location (which is likely a change to the appropriate JNR library).

@headius
Copy link
Member

@headius headius commented Oct 8, 2019

@jacaetevha I am going to basically use the text you provided. Coming up with alternative directory fallback seems fraught with problems, so I'm going to prefer having a warning/error indicating that native support failed to load due to a filesystem issue.

@jacaetevha
Copy link
Author

@jacaetevha jacaetevha commented Oct 8, 2019

👍 Thanks, @headius.

@headius
Copy link
Member

@headius headius commented Oct 8, 2019

I have a patch for JFFI that will enhance the existing errors by indicating what failed and how to remedy it.

For read-only temp location, you'll see the following in jruby.native.verbose output:

... Unable to write jffi binary stub to `/nowrite`. Set `TMPDIR` or Java property `java.io.tmpdir` to a read/write path that is not mounted "noexec".

And for a noexec temp location, the error will be like this:

... Unable to execute or load jffi binary stub from `/dev/shm`. Set `TMPDIR` or Java property `java.io.tmpdir` to a read/write path that is not mounted "noexec".

There's multiple levels of exception-handling and wrapping in this logic, unfortunately, so this message appears somewhat deep in a chain of exceptions...but it's a better error with a remedy.

@jacaetevha
Copy link
Author

@jacaetevha jacaetevha commented Oct 8, 2019

That first error is off a bit...

< ... Unable to write jffi binary stub to `/nowrite`. Set `TMPDIR` or Java property `java.io.tmpdir` to a read/write path that is not mounted "noexec".
> ... Unable to write jffi binary stub to `/nowrite`. Set `TMPDIR` or Java property `java.io.tmpdir` to a read/write path that is not mounted "readonly".

@headius
Copy link
Member

@headius headius commented Oct 8, 2019

I think the original is right...the path needs to be readable and writable (implying it is not readonly) and must not be mounted "noexec" (which is not the same as +x, so I wasn't sure of a better way to say this in few words).

Note I'm using the same remedy for both since the first thing someone might see is a read-only temp and the second thing they might see is noexec, so in both errors the remedy is to set temp to a read-only, non-noexec path.

headius added a commit to jnr/jffi that referenced this issue Oct 8, 2019
When the jffi stub library must be emitted to and loaded from a
local filesystem, we may end up doing so with a path that is
either read-only or "noexec". This change attempts to detect those
cases and inform users about why the error happened and how to
fix it.

See jruby/jruby#5900.
@jacaetevha
Copy link
Author

@jacaetevha jacaetevha commented Oct 8, 2019

Ah, gotcha. Thanks for getting to this so quickly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants