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

intermittent getBlob exception #303

Open
kahing opened this issue Jun 6, 2019 · 9 comments · Fixed by apache/jclouds#150
Open

intermittent getBlob exception #303

kahing opened this issue Jun 6, 2019 · 9 comments · Fixed by apache/jclouds#150

Comments

@kahing
Copy link
Collaborator

kahing commented Jun 6, 2019

I haven't narrowed down what triggers this yet, but goofys CI tests trigger this (unclear which test):

java.util.NoSuchElementException: null
        at java.util.ArrayDeque.removeFirst(ArrayDeque.java:285)
        at com.google.common.io.Closer.close(Closer.java:212)
        at org.jclouds.util.Closeables2.closeQuietly(Closeables2.java:40)
        at org.jclouds.io.payloads.ByteSourcePayload.release(ByteSourcePayload.java:52)
        at org.jclouds.http.internal.PayloadEnclosingImpl.setPayload(PayloadEnclosingImpl.java:56)
        at org.jclouds.blobstore.domain.internal.BlobImpl.setPayload(BlobImpl.java:114)
        at org.jclouds.http.internal.PayloadEnclosingImpl.setPayload(PayloadEnclosingImpl.java:97)
        at org.jclouds.blobstore.config.LocalBlobStore.getBlob(LocalBlobStore.java:723)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.google.inject.internal.DelegatingInvocationHandler.invoke(DelegatingInvocationHandler.java:37)
        at com.sun.proxy.$Proxy40.getBlob(Unknown Source)
        at org.gaul.s3proxy.S3ProxyHandler.handleGetBlob(S3ProxyHandler.java:1640)
        at org.gaul.s3proxy.S3ProxyHandler.doHandle(S3ProxyHandler.java:673)
        at org.gaul.s3proxy.S3ProxyHandlerJetty.handle(S3ProxyHandlerJetty.java:70)
        at org.gaul.shaded.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
        at org.gaul.shaded.org.eclipse.jetty.server.Server.handle(Server.java:499)
        at org.gaul.shaded.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
        at org.gaul.shaded.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
        at org.gaul.shaded.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
        at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
        at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
        at java.lang.Thread.run(Thread.java:748)
@gaul
Copy link
Owner

gaul commented Jun 6, 2019

This is an interesting stack trace! Closer raises an exception in removeFirst below:

    while (!stack.isEmpty()) {
      Closeable closeable = stack.removeFirst();

Closer.register protects against null elements so one would assume that this is impossible without concurrent modification. Yet only a single thread should ever handle this...

@gaul gaul changed the title intermitten GetBlob exception intermittent getBlob exception Jun 8, 2019
@kahing
Copy link
Collaborator Author

kahing commented Sep 12, 2019

another one with a different backtrace:

[s3proxy] W 09-12 05:33:33.879 S3Proxy-Jetty-28 o.g.s.o.e.j.server.HttpChannel:396 |::] /goofys-test-a0gh6o5fe00nh9qu/testLargeFile
java.lang.IllegalStateException: STREAM
	at org.gaul.shaded.org.eclipse.jetty.server.Response.getWriter(Response.java:910)
	at org.gaul.s3proxy.S3ProxyHandler.sendSimpleErrorResponse(S3ProxyHandler.java:2864)
	at org.gaul.s3proxy.S3ProxyHandlerJetty.handle(S3ProxyHandlerJetty.java:146)
	at org.gaul.shaded.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
	at org.gaul.shaded.org.eclipse.jetty.server.Server.handle(Server.java:499)
	at org.gaul.shaded.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
	at org.gaul.shaded.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
	at org.gaul.shaded.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
	at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
	at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
	at java.base/java.lang.Thread.run(Thread.java:834)

This one causes the test to be stuck: https://travis-ci.org/kahing/goofys/jobs/583981057#L11071

@gaul
Copy link
Owner

gaul commented Sep 12, 2019

Does this also happen in getBlob or another operation? The stack trace looks like one of the handlers called getWriter and while emitting some XML it throws an S3Exception. The handler closes the Writer and sendSimpleErrorResponse attempts to reopen it but fails. If you can reproduce this, adding a printStaceTrace will reveal the cause.

@gaul
Copy link
Owner

gaul commented Sep 12, 2019

Actually the line

	at org.gaul.s3proxy.S3ProxyHandlerJetty.handle(S3ProxyHandlerJetty.java:146)

reveals the cause, a TimeoutException, likely from the client. In this case we need more robust handling, first figure out if the stream has be opened and conditionally call into sendSimpleErrorResponse.

@gaul
Copy link
Owner

gaul commented Sep 12, 2019

It looks like sendSimpleErrorResponse should check ServletResponse.isCommitted:

https://docs.oracle.com/javaee/6/api/javax/servlet/ServletResponse.html#isCommitted()

gaul added a commit that referenced this issue Nov 10, 2019
If an error occurs when writing the body of a response, e.g.,
TimeoutException, previously S3Proxy would try to emit the AWS error
code.  Since this stream was already opened and closed, this failed
and Jetty emitted this warning:

Could not send response error 500: java.lang.IllegalStateException:
STREAM

References #303.
@gaul
Copy link
Owner

gaul commented Jul 11, 2020

Similar symptom seen in s3fs CI:

[s3proxy] W 07-09 12:54:28.324 S3Proxy-Jetty-95 o.g.s.o.e.j.server.HttpChannel:396 |::] /s3fs-integration-test/testrun-7332/big-file-s3fs.txt
java.lang.ArrayIndexOutOfBoundsException: -662657112
	at java.util.ArrayDeque.addFirst(ArrayDeque.java:227)
	at com.google.common.io.Closer.register(Closer.java:126)
	at org.jclouds.io.payloads.ByteSourcePayload.openStream(ByteSourcePayload.java:39)
	at org.jclouds.blobstore.config.LocalBlobStore.copyBlob(LocalBlobStore.java:759)
	at org.jclouds.blobstore.config.LocalBlobStore.getBlob(LocalBlobStore.java:677)
	at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.google.inject.internal.DelegatingInvocationHandler.invoke(DelegatingInvocationHandler.java:37)
	at com.sun.proxy.$Proxy40.getBlob(Unknown Source)
	at org.gaul.s3proxy.S3ProxyHandler.handleGetBlob(S3ProxyHandler.java:1712)
	at org.gaul.s3proxy.S3ProxyHandler.doHandle(S3ProxyHandler.java:684)
	at org.gaul.s3proxy.S3ProxyHandlerJetty.handle(S3ProxyHandlerJetty.java:76)
	at org.gaul.shaded.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
	at org.gaul.shaded.org.eclipse.jetty.server.Server.handle(Server.java:499)
	at org.gaul.shaded.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
	at org.gaul.shaded.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
	at org.gaul.shaded.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
	at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
	at org.gaul.shaded.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
	at java.lang.Thread.run(Thread.java:745)

asfgit pushed a commit to apache/jclouds that referenced this issue Jul 11, 2020
This avoids a race condition due to sharing the same Closer instance
and unbounded growth of its Closeable Deque.  References
gaul/s3proxy#303.
@gaul
Copy link
Owner

gaul commented Jun 1, 2021

Fixed in S3Proxy 1.8.0.

@gaul gaul closed this as completed Jun 1, 2021
@gaul
Copy link
Owner

gaul commented Jul 24, 2022

I still see this with S3Proxy 2.0.0:

java.lang.ArrayIndexOutOfBoundsException: Index 12 out of bounds for length 12
        at java.base/java.util.ArrayDeque.grow(ArrayDeque.java:158)
        at java.base/java.util.ArrayDeque.addFirst(ArrayDeque.java:290)
        at com.google.common.io.Closer.register(Closer.java:126)
        at org.jclouds.io.payloads.ByteSourcePayload.openStream(ByteSourcePayload.java:39)
        at org.jclouds.blobstore.config.LocalBlobStore.getBlob(LocalBlobStore.java:741)
        at org.jclouds.blobstore.config.LocalBlobStore.getBlob(LocalBlobStore.java:205)
        at org.jclouds.blobstore.config.LocalBlobStore.blobMetadata(LocalBlobStore.java:762)

@gaul gaul reopened this Jul 24, 2022
gaul added a commit to gaul/jclouds-1 that referenced this issue Jul 24, 2022
Closer is not thread safe and lack of synchronization can throw
ArrayIndexOutOfBoundsExceptions.  Fixes gaul/s3proxy#303.
gaul added a commit to gaul/jclouds-1 that referenced this issue Jul 30, 2022
ByteSourcePayload's.openStream is not thread safe and lack of
synchronization can throw ArrayIndexOutOfBoundsExceptions.
Fixes gaul/s3proxy#303.
gaul added a commit to gaul/jclouds-1 that referenced this issue Aug 1, 2022
ByteSourcePayload.openStream is not thread safe and lack of
synchronization can throw ArrayIndexOutOfBoundsExceptions.  Instead
deep copy the underlying Payload.  Fixes gaul/s3proxy#303.
gaul added a commit to apache/jclouds that referenced this issue Aug 4, 2022
ByteSourcePayload.openStream is not thread safe and lack of
synchronization can throw ArrayIndexOutOfBoundsExceptions.  Instead
deep copy the underlying Payload.  Fixes gaul/s3proxy#303.
@gaul
Copy link
Owner

gaul commented Aug 8, 2022

Needs jclouds 2.6.0 upgrade.

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