-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
Memory Corruption in JNI interface #2472
Comments
@adamretter do you have any idea or suspicion on what could be the trigger of this issue? |
The official release jars are not typically built with DEBUG=0 flag at our end. They are built with something like I am not yet sure on what caused the corruption, but it is interesting to note in the above description that |
@sagar0 I am at a loss for this too because DEBUG=0 only appears to add
but that warning scared me into thinking what else might be happening. In the java Makefile it also removes I'll try to play around with those and see what I can come up with. |
It has something to do with assertions.
Fixes the problem. My guess right now is that there is an assertion protecting the API from some very bad behavior, and there is a test that is doing that bad behavior. With assertions disabled it lets the bad call through and memory is corrupted. I feel much better now, but it would be nice to know what that assertion is, but it is not that critical. |
Okay do I think I can see what is happening here. If we study for example ReadOptionsTest#failsetSnapshotUninitialized. We can see that it explicitly calls public ReadOptions setSnapshot(final Snapshot snapshot) {
assert(isOwningHandle());
if (snapshot != null) {
setSnapshot(nativeHandle_, snapshot.nativeHandle_);
} else {
setSnapshot(nativeHandle_, 0l);
}
return this;
} So the problem is that, when you have Java assertions disabled, i.e. when running the tests in non-debug mode, some of the tests in reinterpret_cast<rocksdb::ReadOptions*>(jhandle)->snapshot =
reinterpret_cast<rocksdb::Snapshot*>(jsnapshot); but that causes a use-after-free leading to a SIGSEGV as the You don't see this when Java assertions are enabled because I think we have a few different options here:
My preferred approach is probably (1) as it prevents Java developers from causing SIGSEGV, which they should never have to worry about. However the overhead could be an issue. @sagar0 @siying your comments please on the approach to take... |
@adamretter Thanks for investigating the issue, and providing a detailed explanation with various options! I agree with you that it might be better to go with option (1) i.e. throw checked exceptions when dealing with use-after-free cases; I agree that it is a lot more JVM-developer-friendly way. With regard to the overhead, I believe that people using RocksJava already accept the larger overhead of running their service on a JVM, and the additional overhead of the CAS you mention in this particular issue may not be significant. Lets try to get some performance numbers to quantify the additional overhead, if any. We can never be certain without benchmarking the overhead. I also think (3) should be the default. Since all our unit tests expect assertions to be enabled, there is no point in running tests without asserts enabled. I am willing to be wrong on this ... and open to discussion, if others in the community have a different view. |
Closing this via automation due to lack of activity. If discussion is still needed here, please re-open or create a new/updated issue. |
I noticed when trying to upgrade to v5.3.6 that when I ran the jtest that it failed 100% of the time with memory corruption errors.
or other times
I found that it only happens when debug is disabled
DEBUG=0
because of that travis does not appear to be detecting it.I setup my own travis run https://travis-ci.org/revans2/rocksdb/builds/245099099 with this enabled and it is failing on both clang and gcc for ubuntu.
I have reproduced the issue using:
g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
Red Hat Enterprise Linux Server release 6.8 (Santiago)
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
and also:
g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)
Red Hat Enterprise Linux Server release 7.1 (Maipo)
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
The exact command I ran was
gmake V=1 PORTABLE=1 DEBUG_LEVEL=0 clean jclean rocksdbjava jtest
Removing
DEBUG_LEVEL=0
make everything work smoothly.Using git bisect I traced it down to #1890 specifically version c6d464a.
For some reason master is not showing this issue. Using git bisect again #2366 (git version c2c62ad) appears to have "fixed" the issue, but unit tests are failing for jtest so I don't know if it really fixed it or if it is just somehow masking the failures.
I don't know how the official 5.4.5, 5.3.6, or 5.3.4 releases or rocksdbjni were built but if they were built with
DEBUG=0
anyone using them runs the risk of memory corruption.The text was updated successfully, but these errors were encountered: