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

JNA: apps built with native-image cannot write into local Unix sockets #4282

Closed
pshirshov opened this issue Jan 31, 2022 · 11 comments
Closed
Assignees

Comments

@pshirshov
Copy link

pshirshov commented Jan 31, 2022

docker-java a popular library, fails to communicate with local docker instances when built by native-image but the same code works perfectly under JVM. It seems to be some kind of a weird problem with JNA built by NI or NI itself, at least docker-java developers think that.

Here is a simple repro: https://github.com/7mind/graalvm-native-image-jna-bad-address-bug-demo

Could you investigate please?

UPD:

  1. Doesn't cannot connect to unix://localhost:80 when compiled with GraalVM docker-java/docker-java#1820 (open)
  2. java.net.Socket fails on local Unix addresses when compiled with GraalVM native image, works well under JVM java-native-access/jna#1412 (closed, not a JNA issue according to the developer, the advice is to call the relevant APIs directly under NI, there are some additional details and diagnostics)
  3. Native builds (GraalVM) run into UnsatisfiedLinkError libjnidispatch.so docker-java/docker-java#1714 (closed, ignored)
@pshirshov
Copy link
Author

I've made a smaller example with a shorter stacktrace: https://github.com/7mind/graalvm-native-image-jna-bad-address-bug-demo/tree/ca7d3578e9081b64fcd0eede6a20d43ada2892ed

Exception in thread "main" java.io.IOException: com.sun.jna.LastErrorException: [14] Bad address
        at com.github.dockerjava.transport.DomainSocket.write(DomainSocket.java:92)
        at com.github.dockerjava.transport.Demo.main(Demo.java:10)
Caused by: com.sun.jna.LastErrorException: [14] Bad address
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_ARRAY_LastErrorException_constructor_d7fda9711fddff58a2e10e04b8efcf48373bdcf5(JNIJavaCallWrappers.java:0)
        at com.oracle.svm.jni.functions.JNIFunctions$NewObjectWithObjectArrayArgFunctionPointer.invoke(JNIFunctions.java)
        at com.oracle.svm.jni.functions.JNIFunctions.ThrowNew(JNIFunctions.java:818)
        at com.github.dockerjava.transport.DomainSocket.write(DomainSocket.java)
        at com.github.dockerjava.transport.DomainSocket.write(DomainSocket.java:90)
        ... 1 more

@pshirshov pshirshov changed the title docker-java (or JNA) fails on local Unix addresses when built by native-image JNA: apps built with native-image cannot write into local Unix sockets Feb 2, 2022
@pshirshov
Copy link
Author

It's interesting that I can read from the socket w/o any problems, private native int read(int fd, ByteBuffer buffer, int count) throws LastErrorException; works. Though private native int write(int fd, ByteBuffer buffer, int count) throws LastErrorException; fails. The signatures are the same.

@pshirshov
Copy link
Author

pshirshov commented Feb 2, 2022

Here is an excerpt from the strace of the native-image:

socketpair(AF_UNIX, SOCK_STREAM, 0, [7, 8]) = 0
shutdown(7, SHUT_RDWR)                  = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 8
setsockopt(8, SOL_SOCKET, SO_PRIORITY, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPIDLE, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPCNT, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPINTVL, [1], 4) = 0
close(8)                                = 0
socket(AF_UNIX, SOCK_STREAM, 0)         = 8
connect(8, {sa_family=AF_UNIX, sun_path="/var/run/docker.sock"}, 110) = 0
write(8, 0x10, 6)                       = -1 EFAULT (Bad address)

@pshirshov
Copy link
Author

pshirshov commented Feb 2, 2022

Another observation: in case I use ByteBuffer.allocateDirect instead of ByteBuffer.wrap write returns an error code and there is no exception being thrown.

The allocation looks like:

        ByteBuffer b = ByteBuffer.allocateDirect(6);
        b.put("GET /\n".getBytes());
        b.position(0);

The corresponding strace:

socketpair(AF_UNIX, SOCK_STREAM, 0, [7, 8]) = 0
shutdown(7, SHUT_RDWR)                  = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 8
setsockopt(8, SOL_SOCKET, SO_PRIORITY, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPIDLE, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPCNT, [1], 4) = 0
close(8)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
setsockopt(8, SOL_TCP, TCP_KEEPINTVL, [1], 4) = 0
close(8)                                = 0
socket(AF_UNIX, SOCK_STREAM, 0)         = 8
connect(8, {sa_family=AF_UNIX, sun_path="/var/run/docker.sock"}, 110) = 0
write(1, "FD: 8", 5FD: 8)                    = 5

Same code works fine under JVM.

@pshirshov
Copy link
Author

pshirshov commented Feb 2, 2022

Seems to be relevant: #2152

That minimal test passes as it is and passes when I modify it to write into /var/run/docker.sock.

@oubidar-Abderrahim oubidar-Abderrahim self-assigned this Feb 4, 2022
@oubidar-Abderrahim
Copy link
Member

Thank you for reporting this, we will take a look into it and get back to you.

@oubidar-Abderrahim
Copy link
Member

Tracked internally at GR--36862

@peterschmidt85
Copy link

I wonder if this issue is relevant too docker-java/docker-java#1820

@pshirshov
Copy link
Author

Yes, it is.

@pshirshov
Copy link
Author

pshirshov commented Jan 4, 2023

@oubidar-Abderrahim @aabbou @loicottet @peter-hofer sorry about pinging you, but was there any progress on this?.. this blocks a lot of possible usecases

@pshirshov
Copy link
Author

Seems like it works on 22.3. Also, oddly, it works on ol8-java17-22.1.0 but not ol8-java11-22.1.0 which I used before.

I'm using https://github.com/oracle/graalvm-reachability-metadata with automatically generated configs.

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

No branches or pull requests

3 participants