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

[SPARK-7660] Wrap SnappyOutputStream to work around snappy-java bug #6176

Closed
wants to merge 1 commit into from

Conversation

JoshRosen
Copy link
Contributor

This patch wraps SnappyOutputStream to ensure that close() is idempotent and to guard against write-after-close() bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent close() method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

@JoshRosen
Copy link
Contributor Author

/cc @rxin @pwendell

@AmplabJenkins
Copy link

Merged build triggered.

@AmplabJenkins
Copy link

Merged build started.

@pwendell
Copy link
Contributor

@JoshRosen does it make sense to re-enable those flakey tests in this patch?

private[this] var closed: Boolean = false

override def write(b: Int): Unit = {
if (closed) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are these guarding against? I understand you'd need it in close, but here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the unlikely event that we wrote to a closed stream, this would end up mutating a buffer that might be shared.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the upstream fix also incorporates this: xerial/snappy-java#108 (comment)

@AmplabJenkins
Copy link

Merged build finished. Test FAILed.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder/32789/
Test FAILed.

@JoshRosen
Copy link
Contributor Author

Jenkins, retest this please.

@JoshRosen
Copy link
Contributor Author

@pwendell, my hotfix didn't disable the tests; instead, it added a workaround in another test suite that clears the pool of reusable Snappy buffers, fixing the JavaAPISuite failures (I tested this locally before pushing the hotfix).

@AmplabJenkins
Copy link

Merged build triggered.

@AmplabJenkins
Copy link

Merged build started.

@SparkQA
Copy link

SparkQA commented May 15, 2015

Test build #32793 has started for PR 6176 at commit 8b77aae.

@SparkQA
Copy link

SparkQA commented May 15, 2015

Test build #32793 has finished for PR 6176 at commit 8b77aae.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Merged build finished. Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder/32793/
Test PASSed.

@pwendell
Copy link
Contributor

@JoshRosen ah totally understand - got it.

*/
private final class SnappyOutputStreamWrapper(os: SnappyOutputStream) extends OutputStream {

private[this] var closed: Boolean = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checking - this doesn't need to be volatile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point. I guess this needs to be volatile in case we're performing cleanup in another thread. @rxin, if this is volatile, won't that make the write() checks way more expensive?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we already do per-record checking of volatile vars.

https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/TaskContextImpl.scala#L44

On Fri, May 15, 2015 at 4:40 PM, Josh Rosen notifications@github.com
wrote:

In core/src/main/scala/org/apache/spark/io/CompressionCodec.scala
#6176 (comment):

}

override def compressedInputStream(s: InputStream): InputStream = new SnappyInputStream(s)
}
+
+/**

  • * Wrapper over [[SnappyOutputStream]] which guards against write-after-close and double-close
  • * issues. See SPARK-7660 for more details. This wrapping can be removed if we upgrade to a version
  • * of snappy-java that contains the fix for SnappyOutputStream.close() is not idempotent xerial/snappy-java#107.
  • */
    +private final class SnappyOutputStreamWrapper(os: SnappyOutputStream) extends OutputStream {
    +
  • private[this] var closed: Boolean = false

Ah, good point. I guess this needs to be volatile in case we're performing
cleanup in another thread. @rxin https://github.com/rxin, if this is
volatile, won't that make the write() checks way more expensive?


Reply to this email directly or view it on GitHub
https://github.com/apache/spark/pull/6176/files#r30454371.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this offline: as far as we know, this is only ever executed in a single-threaded context (since tasks are single-threaded and their stop / cleanup logic is performed in that same thread), so the volatile should not be necessary.

@pwendell
Copy link
Contributor

Josh this LGTM - if there are no outstanding comments we should try to get this in since it's one of the few remaining blockers.

@rxin
Copy link
Contributor

rxin commented May 17, 2015

LGTM.

@JoshRosen
Copy link
Contributor Author

I'm going to merge this into master and branch-1.4, then will cherry-pick back to 1.3.x and 1.2.x. Thanks for the reviews.

asfgit pushed a commit that referenced this pull request May 17, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes #6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660

(cherry picked from commit f2cc6b5)
Signed-off-by: Josh Rosen <joshrosen@databricks.com>
@asfgit asfgit closed this in f2cc6b5 May 17, 2015
asfgit pushed a commit that referenced this pull request May 17, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes #6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660

(cherry picked from commit f2cc6b5)
Signed-off-by: Josh Rosen <joshrosen@databricks.com>

Conflicts:
	core/src/main/scala/org/apache/spark/io/CompressionCodec.scala
	core/src/test/java/org/apache/spark/shuffle/unsafe/UnsafeShuffleWriterSuite.java
asfgit pushed a commit that referenced this pull request May 17, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes #6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660

(cherry picked from commit f2cc6b5)
Signed-off-by: Josh Rosen <joshrosen@databricks.com>

Conflicts:
	core/src/main/scala/org/apache/spark/io/CompressionCodec.scala
	core/src/test/java/org/apache/spark/shuffle/unsafe/UnsafeShuffleWriterSuite.java
@JoshRosen JoshRosen deleted the SPARK-7660-wrap-snappy branch May 26, 2015 03:41
jeanlyn pushed a commit to jeanlyn/spark that referenced this pull request May 28, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes apache#6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660
jeanlyn pushed a commit to jeanlyn/spark that referenced this pull request Jun 12, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes apache#6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660
nemccarthy pushed a commit to nemccarthy/spark that referenced this pull request Jun 19, 2015
This patch wraps `SnappyOutputStream` to ensure that `close()` is idempotent and to guard against write-after-`close()` bugs. This is a workaround for xerial/snappy-java#107, a bug where a non-idempotent `close()` method can lead to stream corruption. We can remove this workaround if we upgrade to a snappy-java version that contains my fix for this bug, but in the meantime this patch offers a backportable Spark fix.

Author: Josh Rosen <joshrosen@databricks.com>

Closes apache#6176 from JoshRosen/SPARK-7660-wrap-snappy and squashes the following commits:

8b77aae [Josh Rosen] Wrap SnappyOutputStream to fix SPARK-7660
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants