Menu

Commit [r12]  Maximize  Restore  History

Do not use longjmp to clear the stack after Apache has aborted the connection. Instead jump back to java, then throw an exception, then longjmp to our main loop

jost2345 2004-09-12

changed /trunk/php-java-bridge/ChangeLog
changed /trunk/php-java-bridge/server/natcJavaBridge.c
/trunk/php-java-bridge/ChangeLog Diff Switch to side-by-side view
--- a/trunk/php-java-bridge/ChangeLog
+++ b/trunk/php-java-bridge/ChangeLog
@@ -29,6 +29,17 @@
 	jdk1.4 correctly.
 	* bind.c: Pass modified environment on to the child process.
 
-2004-09-11  Jost Boekemeier  <jost2345@mail.yahoo.de>
+2004-09-12  Jost Boekemeier  <jost2345@mail.yahoo.de>
 
-	* README: Describe GNU Java support
+	* README: GNU Java supported
+
+	The SUN Java implementation may store objects on the stack.
+	Objects on the heap may reference them. So in this JVM we cannot
+	simply longjmp to clear the stack, because some heap objects may
+	still refer to dead locations.  The result would be that the VM
+	will barf when the GC tries to follow these phantom references.
+	* natcJavaBridge.c: Longjmp to the last savepoint, then return
+	back to java, throw an exception to return to one of the three
+	native main methods and then jump back to the loop.  This fixes a
+	crash in the SUN VM which occured after apache has aborted the
+	connection.
/trunk/php-java-bridge/server/natcJavaBridge.c Diff Switch to side-by-side view
--- a/trunk/php-java-bridge/server/natcJavaBridge.c
+++ b/trunk/php-java-bridge/server/natcJavaBridge.c
@@ -38,8 +38,10 @@
 #define ASSERTM(expr) \
 if(!expr) { \
   logMemoryError(env, __FILE__, __LINE__); \
-  longjmp(peer->env, 6); \
-}
+  exit(6); \
+}
+
+static jclass exceptionClass=NULL;
 
 static jclass hashClass=NULL;
 static jmethodID init=NULL;
@@ -58,7 +60,10 @@
 static pthread_attr_t attr;
 
 struct peer {
-  jmp_buf env;
+  jmp_buf env;					/* exit from the loop */
+  jmp_buf savepoint;			/* jump back to java */
+  JNIEnv *jenv;
+  short tran;					/* if we must return to java first */
   FILE*stream;
   jobject objectHash;
 };
@@ -97,20 +102,33 @@
   static char s[512];
   sprintf(s, "system error: out of memory error in: %s, line: %d", file, pos);
   logError(jenv, s);
-  abort();
+  exit(9);
 }
 
 static void swrite(const  void  *ptr,  size_t  size,  size_t  nmemb,  struct peer*peer) {
   FILE*stream=peer->stream;
   int n = fwrite(ptr, size, nmemb, stream);
   //printf("write char:::%d\n", (unsigned int) ((char*)ptr)[0]);
-  if(n!=nmemb) longjmp(peer->env, 2);
+  if(n!=nmemb) {
+	if(peer->tran) {		/* first clear the java stack, then longjmp */
+	  (*peer->jenv)->ThrowNew(peer->jenv, exceptionClass, "child aborted connection during write");
+	  longjmp(peer->savepoint, 1);
+	} else
+	   longjmp(peer->env, 2);
+  }
+
 }
 static void sread(void *ptr, size_t size, size_t nmemb, struct peer *peer) {
   FILE*stream=peer->stream;
   int n = fread(ptr, size, nmemb, stream);
   //printf("read char:::%d\n", (unsigned int) ((char*)ptr)[0]);
-  if(n!=nmemb) longjmp(peer->env, 1);
+  if(n!=nmemb) {
+	if(peer->tran) {		/* first clear the java stack, then longjmp */
+	  (*peer->jenv)->ThrowNew(peer->jenv, exceptionClass, "child aborted connection during read");
+	  longjmp(peer->savepoint, 1);
+	} else
+	  longjmp(peer->env, 1);
+  }
 }
 
 static void id(struct peer*peer, char id) {
@@ -145,13 +163,13 @@
 	pthread_attr_destroy(&attr);
   }
 }
-static jmp_buf signal_env;
 static void exit_sig(int dummy) {
-  longjmp(signal_env, 1);
+  exit(0);
 }
 static void initGlobals(JNIEnv *env) {
   jobject hash;
 
+  exceptionClass = (*env)->FindClass(env, "java/lang/Throwable");
   hashClass = (*env)->FindClass(env, "java/util/Hashtable");
   init = (*env)->GetMethodID(env, hashClass, "<init>", "()V");
   hash = (*env)->NewObject(env, hashClass, init);
@@ -209,13 +227,22 @@
 	jstring method;
 	jobjectArray array;
 	jlong result;
+	jthrowable abort;
+
 	sread(&php_reflect, sizeof php_reflect,1, peer);
 	sread(&invoke, sizeof invoke,1, peer);
 	sread(&obj, sizeof obj,1, peer);
 	sread(&method, sizeof method,1, peer);
 	sread(&array, sizeof array,1, peer);
 	sread(&result, sizeof result,1, peer);
+	peer->tran=1;
 	(*env)->CallVoidMethod(env, php_reflect, invoke, obj, method, array, result, (jlong)(long)peer);
+	abort = (*env)->ExceptionOccurred(env);
+	if(abort) {  /* connection aborted by client, java stack cleared */
+	  (*env)->ExceptionClear(env);
+	  peer->tran=0;
+	  longjmp(peer->env, 1);
+	}
 	ID(peer, 0);
 	break;
   }
@@ -225,12 +252,21 @@
 	jstring method;
 	jobjectArray array;
 	jlong result;
+	jthrowable abort;
+
 	sread(&php_reflect, sizeof php_reflect,1, peer);
 	sread(&invoke, sizeof invoke,1, peer);
 	sread(&method, sizeof method,1, peer);
 	sread(&array, sizeof array,1, peer);
 	sread(&result, sizeof result,1, peer);
+	peer->tran=1;
 	(*env)->CallVoidMethod(env, php_reflect, invoke, method, array, result, (jlong)(long)peer);
+	abort = (*env)->ExceptionOccurred(env);
+	if(abort) { /* connection aborted by client, java stack cleared */
+	  (*env)->ExceptionClear(env);
+	  peer->tran=0;
+	  longjmp(peer->env, 1);
+	}
 	ID(peer, 0);
 	break;
   }
@@ -504,12 +540,15 @@
   int val;
   peer.objectHash=initHash(env);
   if(!peer.objectHash) {logError(env, "could not create hash table"); return -40;}
+  peer.stream=file;
+  peer.jenv=env;
+  peer.tran=0;
+
   val=setjmp(peer.env);
   if(val) {
 	(*env)->DeleteGlobalRef(env, peer.objectHash);
 	return -val;
   }
-  peer.stream=file;
   val=handle_request(&peer, env);
   (*env)->DeleteGlobalRef(env, peer.objectHash);
   return val;
@@ -563,8 +602,6 @@
   pthread_t thread;
   struct sockaddr_un saddr;
   int sock, n;
-
-  if(setjmp(signal_env)) return; //sigkill arrived
 
   initGlobals(env);
   logLevel = _logLevel;
@@ -612,6 +649,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jbyteArray value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMSTRING);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
@@ -622,6 +660,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jlong value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMLONG);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
@@ -632,6 +671,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jdouble value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMDOUBLE);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
@@ -642,6 +682,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jboolean value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMBOOLEAN);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
@@ -652,6 +693,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jobject value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMOBJECT);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
@@ -662,6 +704,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETRESULTFROMARRAY);
   swrite(&result, sizeof result, 1, peer);
   while(handle_request(peer, env));
@@ -672,6 +715,7 @@
 {
   jlong result;
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return 0;
   ID(peer, NEXTELEMENT);
   swrite(&array, sizeof array, 1, peer);
   while(handle_request(peer, env));
@@ -685,6 +729,7 @@
 {
   jlong result;
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return 0;
   ID(peer, HASHINDEXUPDATE);
   swrite(&array, sizeof array, 1, peer);
   swrite(&key, sizeof key, 1, peer);
@@ -698,6 +743,7 @@
 {
   jlong result;
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return 0;
   ID(peer, HASHUPDATE);
   swrite(&array, sizeof array, 1, peer);
   swrite(&key, sizeof key, 1, peer);
@@ -711,6 +757,7 @@
   (JNIEnv *env, jclass self, jlong result, jlong _peer, jbyteArray value)
 {
   struct peer*peer=(struct peer*)(long)_peer;
+  if(setjmp(peer->savepoint)) return;
   ID(peer, SETEXCEPTION);
   swrite(&result, sizeof result, 1, peer);
   swrite(&value, sizeof value, 1, peer);
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.