Committed in r947006. I tweaked the patch just a bit to ensure we catch any exceptions generated. Please confirm that it still functions as expected.
Thanks! -Hyrum On Thu, May 20, 2010 at 5:13 PM, Byeongcheol Lee <[email protected]>wrote: > Dear Subversion Developers: > > I attach a patch for a local reference leak in Outter.cpp, and the log > message follows here: > > [[[ > * subversion/bindings/javahl/native/Outputer.cpp > (write): add a call to "DeleteLocalRef" where a leaking local > reference is unreachable. > ]]] > > To reproduce this bug, run your javaHL regression test under our > dynamic bug detector, JInn > [http://userweb.cs.utexas.edu/~bclee/jinn<http://userweb.cs.utexas.edu/%7Ebclee/jinn> > ]: > > $env JAVA_TOOL_OPTIONS=-agentlib:jinn make check-javahl > ... > .Exception in thread "main" xtc.lang.blink.agent.JNIAssertionFailure: > The number of local references exceeds the current capacity 16 in > NewByteArray. > at > xtc.lang.blink.agent.JNIAssertionFailure.assertFail(JNIAssertionFailure.java:16) > at org.apache.subversion.javahl.SVNAdmin.dump(Native Method) > at org.apache.subversion.javahl.SVNAdmin.dump(SVNAdmin.java:128) > at org.apache.subversion.javahl.SVNTests.setUp(SVNTests.java:241) > at junit.framework.TestCase.runBare(TestCase.java:128) > ... > at org.apache.subversion.javahl.RunTests.main(RunTests.java:116) > ... > > The local reference leak happens when a Java native method creates > more than 16 local references without deleting unreachable references > (DeleteLocalRef), adjusting capacity (EnsureLocalCapacity) or > allocating a local frame (PushLocalFrame). The Subversion r946780 > violates this JNI programming rule: > > "The JNI specification dictates that the virtual machine automatically > ensures that each native method can create at least 16 local > references. Experience shows that this provides enough capacity for > the majority of native methods that do not contain complex > interactions with objects in the Java virtual machine. If, however, > there is a need to create additional local references, a native method > may issue an EnsureLocalCapacity call to make sure that space for a > sufficient number of local references is available. For example, a > slight variation of a previous example above reserves enough capacity > for all local references created during the loop execution if > sufficient memory is available:" > [http://java.sun.com/docs/books/jni/html/refs.html#27592] > > I attached gdb to the JVM, and examined every JNI call that allocates > a local reference, and I ended up the leaking allocation site at Line > 99 in subversion/bindings/javahl/native/Outputer.cpp: > > ... > 73 svn_error_t *Outputer::write(void *baton, const char *buffer, > apr_size_t *len) > 74 { > ... > 99 jbyteArray data = JNIUtil::makeJByteArray((const signed > char*)buffer, > 100 *len); > 101 if (JNIUtil::isJavaExceptionThrown()) > 102 return SVN_NO_ERROR; > 103 > 104 // write the data > 105 jint written = env->CallIntMethod(that->m_jthis, mid, data); > 106 if (JNIUtil::isJavaExceptionThrown()) > 107 return SVN_NO_ERROR; > 108 > 109 // return the number of bytes written > 110 *len = written; > 111 > 112 return SVN_NO_ERROR; > 113 } > > This "write" method does not delete the local reference in the > variable "data" at Line 99 when it returns. In the test run, this > "write" method was activated more than 16 times. The simplest fix is > adding "env->DeleteLocalRef(data)" after Line 105 where the "data" > variable is not used in the future. Even if Line 105 throws a Java > exception, it's fine because "DeleteLocalRef" is one of 20 > exception-oblivious function: > > "After an exception has been raised, the native code must first clear > the exception before making other JNI calls. When there is a pending > exception, the JNI functions that are safe to call are: > .... > DeleteLocalRef() > ...." [ > http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp770 > ] > > For your information, here are calling contexts that allocate 16 > unreachable local references: > > 1 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1072 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 2 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1075 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 3 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:985 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1101 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 4 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:988 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1101 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 5 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:995 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1101 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 6 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > write_revision_record at subversion/libsvn_repos/dump.c:1001 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1101 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 7 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > write_revision_record at subversion/libsvn_repos/dump.c:1004 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1101 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 8 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > repos_progress_handler at subversion/libsvn_repos/deprecated.c:454 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1159 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 9 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:985 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1119 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 10 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:988 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1119 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 11 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > write_revision_record at subversion/libsvn_repos/dump.c:995 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1119 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 12 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > write_revision_record at subversion/libsvn_repos/dump.c:1001 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1119 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 13 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > write_revision_record at subversion/libsvn_repos/dump.c:1004 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1119 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 14 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > dump_node at subversion/libsvn_repos/dump.c:330 > add_directory at subversion/libsvn_repos/dump.c:723 > path_driver_cb_func at subversion/libsvn_repos/replay.c:450 > svn_delta_path_driver at subversion/libsvn_delta/path_driver.c:254 > svn_repos_replay2 at subversion/libsvn_repos/replay.c:777 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1152 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 15 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > dump_node at subversion/libsvn_repos/dump.c:337 > add_directory at subversion/libsvn_repos/dump.c:723 > path_driver_cb_func at subversion/libsvn_repos/replay.c:450 > svn_delta_path_driver at subversion/libsvn_delta/path_driver.c:254 > svn_repos_replay2 at subversion/libsvn_repos/replay.c:777 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1152 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > 16 > Outputer::write at subversion/bindings/javahl/native/Outputer.cpp:101 > svn_stream_write at subversion/libsvn_subr/stream.c:153 > svn_stream_printf at subversion/libsvn_subr/stream.c:209 > dump_node at subversion/libsvn_repos/dump.c:417 > add_directory at subversion/libsvn_repos/dump.c:723 > path_driver_cb_func at subversion/libsvn_repos/replay.c:450 > svn_delta_path_driver at subversion/libsvn_delta/path_driver.c:254 > svn_repos_replay2 at subversion/libsvn_repos/replay.c:777 > svn_repos_dump_fs3 at subversion/libsvn_repos/dump.c:1152 > svn_repos_dump_fs2 at subversion/libsvn_repos/deprecated.c:480 > SVNAdmin::dump at subversion/bindings/javahl/native/SVNAdmin.cpp:210 > Java_org_apache_subversion_javahl_SVNAdmin_dump at > org_apache_subversion_javahl_SVNAdmin.cpp:165 > > Regards, > Byeong >

