Author: amiloslavskiy Date: Thu Oct 15 10:17:19 2020 New Revision: 1882524 URL: http://svn.apache.org/viewvc?rev=1882524&view=rev Log: JavaHL: Make sure that TunnelAgent is cleaned up on pending exception
See the previous commit for explanation why cleanup is important. Before this commit, if there was a pending Java exception (such as SVN error), 'OperationContext::closeTunnel()' early-returned on 'isJavaExceptionThrown()'. At the same time, calling Java methods in 'close_TunnelChannel()' requires that there are no pending Java exceptions. Use 'StashException' to temporarily move it out of the way. This crash is demonstrated by the following JavaHL tests: * testCrash_RequestChannel_nativeRead_AfterException * testCrash_RequestChannel_nativeRead_AfterSvnError This commit alone does not fix all problems in these tests, see previous and next commits as well. [in subversion/bindings/javahl] * native/OperationContext.cpp Use 'StashException' to move temporarily exception out of the way. Modified: subversion/branches/javahl-1.14-fixes/subversion/bindings/javahl/native/OperationContext.cpp Modified: subversion/branches/javahl-1.14-fixes/subversion/bindings/javahl/native/OperationContext.cpp URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.14-fixes/subversion/bindings/javahl/native/OperationContext.cpp?rev=1882524&r1=1882523&r2=1882524&view=diff ============================================================================== --- subversion/branches/javahl-1.14-fixes/subversion/bindings/javahl/native/OperationContext.cpp (original) +++ subversion/branches/javahl-1.14-fixes/subversion/bindings/javahl/native/OperationContext.cpp Thu Oct 15 10:17:19 2020 @@ -691,19 +691,25 @@ OperationContext::closeTunnel(void *tunn delete tc; JNIEnv *env = JNIUtil::getEnv(); - if (JNIUtil::isJavaExceptionThrown()) - return; + + // Cleanup is important, otherwise TunnelAgent may crash when + // accessing freed native objects. For this reason, cleanup is done + // despite a pending exception. If more exceptions occur, they are + // stashed as well in order to complete all cleanup steps. + StashException ex(env); if (jclosecb) callCloseTunnelCallback(env, jclosecb); if (jrequest) { + ex.stashException(); close_TunnelChannel(env, jrequest); } if (jresponse) { + ex.stashException(); close_TunnelChannel(env, jresponse); } }