Author: [EMAIL PROTECTED]
Date: Fri Sep 26 23:18:55 2008
New Revision: 3690

Modified:
    changes/jat/oophm-branch/plugins/common/HostChannel.cpp
    changes/jat/oophm-branch/plugins/common/SessionHandler.h
    changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp
    changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h
    changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp

Log:
Fixed JavaObject freeing and handled calls happening after the channel has
gone away.  Seems pretty solid at this point with no major memory leaks
(not tested carefully, but running for a couple of hours with events going
on doesn't grow firefox a lot).

To do:
  - verify this fixes the Windows/OSX crashes
  - run end-to-end tests
  - clean up build system



Modified: changes/jat/oophm-branch/plugins/common/HostChannel.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/common/HostChannel.cpp     (original)
+++ changes/jat/oophm-branch/plugins/common/HostChannel.cpp     Fri Sep 26  
23:18:55 2008
@@ -203,6 +203,7 @@
            Value returnValue;
            bool exception = handler->invoke(*this, imsg->getThis(),  
imsg->getMethodName(),
                imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+          handler->sendFreeValues(*this);
            ReturnMessage::send(*this, exception, returnValue);
          }
          break;
@@ -217,6 +218,7 @@
            Value returnValue;
            bool exception = handler->invokeSpecial(*this,  
imsg->getDispatchId(),
                imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+          handler->sendFreeValues(*this);
            ReturnMessage::send(*this, exception, returnValue);
          }
          break;

Modified: changes/jat/oophm-branch/plugins/common/SessionHandler.h
==============================================================================
--- changes/jat/oophm-branch/plugins/common/SessionHandler.h    (original)
+++ changes/jat/oophm-branch/plugins/common/SessionHandler.h    Fri Sep 26  
23:18:55 2008
@@ -71,6 +71,11 @@
    virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method,  
int numArgs,
        const Value* const args, Value* returnValue) = 0;

+  /**
+   * Send any queued up free values back to the server.
+   */
+  virtual void sendFreeValues(HostChannel& channel) = 0;
+
    virtual ~SessionHandler() {}
  };


Modified: changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp (original)
+++ changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp Fri Sep 26  
23:18:55 2008
@@ -23,6 +23,7 @@
  #include "scoped_ptr/scoped_ptr.h"
  #include "RootedObject.h"
  #include "InvokeMessage.h"
+#include "ServerMethods.h"

  #include "jsapi.h"
  #include "nsCOMPtr.h"
@@ -133,6 +134,21 @@
    }
  }

+void FFSessionHandler::sendFreeValues(HostChannel& channel) {
+  unsigned n = javaObjectsToFree.size();
+  if (n) {
+    scoped_array<int> ids(new int[n]);
+    int i = 0;
+    for (std::set<int>::iterator it = javaObjectsToFree.begin();
+        it != javaObjectsToFree.end(); ++it) {
+      ids[i++] = *it;
+    }
+    if (ServerMethods::freeJava(channel, this, n, ids.get())) {
+      javaObjectsToFree.clear();
+    }
+  }
+}
+
  bool FFSessionHandler::invoke(HostChannel& channel, const Value& thisObj,  
const std::string& methodName,
      int numArgs, const Value* const args, Value* returnValue) {
    Debug::log(Debug::Spam) << "FFSessionHandler::invoke " <<  
thisObj.toString()
@@ -357,7 +373,6 @@
    }
  }

-// TODO(jat): actually free objects from javaObjectsToFree
  void FFSessionHandler::freeJavaObject(int objectId) {
    if (!javaObjectsById.erase(objectId)) {
      Debug::log(Debug::Error) << "Trying to free unknown JavaObject: " <<  
objectId << Debug::flush;
@@ -381,11 +396,25 @@
        jsObjectsById = NULL;
      }
      JS_RemoveRoot(ctx, &toStringTearOff);
+    for (std::map<int, JSObject*>::iterator it = javaObjectsById.begin();
+        it != javaObjectsById.end(); ++it) {
+      int javaId = it->first;
+      JSObject* obj = it->second;
+      if (JavaObject::isJavaObject(ctx, obj)) {
+        // clear the SessionData pointer -- JavaObject knows it is
+        // disconnected if this is null
+        JS_SetPrivate(ctx, obj, NULL);
+        javaObjectsToFree.erase(javaId);
+      }
+    }
      JS_EndRequest(ctx);
      contextMap.erase(ctx);
      ctx = NULL;
    }
-  getHostChannel()->disconnectFromHost();
+  HostChannel* channel = getHostChannel();
+  if (channel->isConnected()) {
+    channel->disconnectFromHost();
+  }
  }

  static JSBool contextCallback(JSContext* ctx, uintN contextOp) {

Modified: changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h   (original)
+++ changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h   Fri Sep 26  
23:18:55 2008
@@ -31,6 +31,7 @@
    public SessionData,
    public SessionHandler
  {
+  friend class JavaObject;
  public:
    FFSessionHandler(HostChannel* channel);
    ~FFSessionHandler(void);
@@ -47,6 +48,7 @@
        int numArgs, const Value* const args, Value* returnValue);
    virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method,  
int numArgs,
        const Value* const args, Value* returnValue);
+  virtual void sendFreeValues(HostChannel& channel);

  private:
    static void registerHandler(JSContext* context, FFSessionHandler*  
handler);

Modified: changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp       (original)
+++ changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp       Fri Sep 26  
23:18:55 2008
@@ -46,7 +46,7 @@
    NULL, /* object serialization */
    NULL, /* has instance */
    NULL, /* mark */
-  NULL /* reserved slots */
+  NULL /* reserve slots */
  };

  int JavaObject::getObjectId(JSContext* ctx, JSObject* obj) {
@@ -113,21 +113,26 @@
    return obj;
  }

-JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsval id,  
jsval* vp) {
+JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsval id,
+    jsval* rval) {
    Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj <<  
Debug::flush;
    SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
    int objectRef = JavaObject::getObjectId(ctx, obj);
    if (JSVAL_IS_STRING(id)) {
      JSString* str = JSVAL_TO_STRING(id);
  #if 1
      if ((JS_GetStringLength(str) == 8) && !strncmp("toString",
            JS_GetStringBytes(str), 8)) {
-      *vp = data->getToStringTearOff();
+      *rval = data->getToStringTearOff();
        return JS_TRUE;
      }
      if ((JS_GetStringLength(str) == 2) && !strncmp("id",
            JS_GetStringBytes(str), 2)) {
-      *vp = INT_TO_JSVAL(objectRef);
+      *rval = INT_TO_JSVAL(objectRef);
        return JS_TRUE;
      }
  #endif
@@ -146,22 +151,26 @@
    SessionHandler* handler = data->getSessionHandler();

    Value value = ServerMethods::getProperty(*channel, handler, objectRef,  
dispId);
-  data->makeValueRef(*vp, ctx, value);
+  data->makeValueRef(*rval, ctx, value);
    return JS_TRUE;
  }

-JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsval id,  
jsval* vp) {
+JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsval id,
+    jsval* vp) {
    Debug::log(Debug::Spam) << "JavaObject::setProperty obj=" << obj <<  
Debug::flush;
    if (!JSVAL_IS_INT(id)) {
      Debug::log(Debug::Error) << "  Error: setting string property id" <<  
Debug::flush;
      return JS_FALSE;
    }

+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    return JS_TRUE;
+  }
+
    int objectRef = JavaObject::getObjectId(ctx, obj);
    int dispId = JSVAL_TO_INT(id);

-  SessionData* data = JavaObject::getSessionData(ctx, obj);
-
    Value value;
    data->makeValue(value, ctx, *vp);

@@ -245,16 +254,19 @@
    Debug::log(Debug::Debugging) << "JavaObject::finalize obj=" << obj
        << " objId=" << JavaObject::getObjectId(ctx, obj) << Debug::flush;
    SessionData* data = JavaObject::getSessionData(ctx, obj);
-  int objectId = JavaObject::getObjectId(ctx, obj);
-  // TODO(jat): data can be invalid at the point this is called, causing a
-  // crash -- need to consider how to make sure it is kept around or that  
we
-  // have some way of telling it is gone so we can ignore it.
-  // data->freeJavaObject(objectId);
+  if (data) {
+    int objectId = JavaObject::getObjectId(ctx, obj);
+    data->freeJavaObject(objectId);
+  }
  }

-JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,  
jsval* argv,
-    jsval* rval) {
+JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,
+    jsval* argv, jsval* rval) {
    SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
    int oid = getObjectId(ctx, obj);
    Debug::log(Debug::Spam) << "JavaObject::toString(id=" << oid << ")"
        << Debug::flush;
@@ -275,7 +287,8 @@
   * the exception which was thrown.  In this case, we always return false  
and
   * raise the exception ourselves.
   */
-JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval*  
argv, jsval* rval) {
+JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval* argv,
+    jsval* rval) {
    // Get the JavaObject called as a function
    JSObject* obj = JSVAL_TO_OBJECT(argv[-2]);
    if (argc < 2 || !JSVAL_IS_INT(argv[0]) || !JSVAL_IS_OBJECT(argv[1])) {
@@ -294,6 +307,10 @@
    dbg << ")" << Debug::flush;

    SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
    Debug::log(Debug::Spam) << "Data = " << data << Debug::flush;

    Value javaThis;
@@ -338,6 +355,7 @@
      // Debug::log(Debug::Spam) << "   " << dumpJsVal(ctx, jsargs[i]) <<  
Debug::flush;
      data->makeValue(args[i], ctx, jsargs[i]);
    }
+//  static_cast<FFSessionHandler*>(handler)->sendFreeValues(*channel);
    if (!InvokeMessage::send(*channel, javaThis, dispId, numArgs,  
args.get())) {
      Debug::log(Debug::Error) << "JavaObject::call failed to send invoke  
message" << Debug::flush;
      return false;

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to