Crash: blocking JS and deleting a window

Koos Vriezen koos.vriezen at xs4all.nl
Sat Oct 5 16:41:40 BST 2002


On Sat, 5 Oct 2002, Koos Vriezen wrote:

> On Sat, 5 Oct 2002, Koos Vriezen wrote:
>
> > On Sat, 5 Oct 2002, Simon Hausmann wrote:
> > >
> > > On a second though I don't understand how this can happen. The
> > > alert() triggers a messagebox with the window as parent, so it
> > > shouldn't be possible to close the window in the first place as the
> > > messagebox is modal. Any idea?
> >
> > Same for 'Open Location' dialog. Bug in Qt?
> >
> > There are other cases, eg calls to Java, that could block JS. Something
> > has to be done.
>
> Well, if this modal dialog can be solved elsewhere, we might not need a
> canDelete event if this ugly synchronization in KJavaAppletServer can be
> implemented differently:
>     while (!frame->ready && --count > 0) {
>         usleep(50000);
>         qApp->processEvents(100);
>     }
> Solution that I can think of is
> - Running kjs in a subprocess that can be killed
> - Return from evaluate with completion type UNFINISHED and continues
>   running after data is arrived (or timed out)
> Both not very feasible (certainly for 3.1)
>
> Other suggestions?

Attached an attempt to stop blocking JS (line numbers maybe wrong). Where
should I put the 'stopLiveConnect()' call. Implemented like this, a crash
in KHTMLPart::clear occurs, when trying to close the
teletext window from http://www.n-tv.de. Some console traces:

kparts: Part::~Part 0x88038a0
kparts: deleting widget [KHTMLView pointer (0x8803b18) to widget kopf,
geometry=662x60+2000+2000] kopf
kjas: KJavaAppletServer::stopLiveConnect 0x87f45c0
kjas: KJavaAppletServer::stopLiveConnect framecount:1
  One active JS blocking call
kjas: KJavaProcess::storeSize, size =        6
kjas: KJavaProcess::storeSize, size =        6
  kjas continues with this call
......
kparts: KPart::slotWidgetDestroyed(), deleting part main
.....
kparts: Part::~Part 0x8786ad8
kparts: KPart::slotWidgetDestroyed(), deleting part <!--frame 1-->
kparts: Part::~Part 0x86d1ec0
kparts: KPart::slotWidgetDestroyed(), deleting part bottom
kparts: 0x873d288 emitting activePartChanged (nil)
khtml (jscript): Window::clear 0x86ba134
.......
kparts: Part::~Part 0x87f0ad0
kjas: KJavaAppletServer::slotJavaRequest: 2
kjas: KJavaAppletServer::slotJavaRequest: 0
kjas: KJavaAppletServer::slotJavaRequest:
kjas: ERROR: no context object for this id
kjas: KJavaAppletServer::stopLiveConnect after recount 0
  No active blocking calls  left
CRASH

Seems like implemented like this, its too late (doesn't help to put it in
KHTMLPart::~KHTMLPart before clear().

>
> Koos
>
>
-------------- next part --------------
Index: khtml_part.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtml_part.cpp,v
retrieving revision 1.751
diff -u -3 -p -r1.751 khtml_part.cpp
--- khtml_part.cpp	2002/09/29 09:25:33	1.751
+++ khtml_part.cpp	2002/10/05 14:42:18
@@ -854,6 +859,12 @@ void KHTMLPart::clear()
   if ( d->m_bCleared )
     return;
   d->m_bCleared = true;
+
+#ifndef Q_WS_QWS
+  // make sure we don't have any JS doing blocking Java calls
+  if( d->m_javaContext )
+    d->m_javaContext->stopLiveConnect();
+#endif
 
   d->m_bClearing = true;
 
Index: java/kjavaappletserver.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/kjavaappletserver.cpp,v
retrieving revision 1.53
diff -u -3 -p -r1.53 kjavaappletserver.cpp
--- java/kjavaappletserver.cpp	2002/09/22 13:18:58	1.53
+++ java/kjavaappletserver.cpp	2002/10/05 14:42:18
@@ -63,14 +63,19 @@
 #define KJAS_AUDIOCLIP_PLAY    (char)20
 #define KJAS_AUDIOCLIP_LOOP    (char)21
 #define KJAS_AUDIOCLIP_STOP    (char)22
 
 
 class JSStackNode {
 public:
-    JSStackNode(JSStackNode *u) : ready(false), size(u ? u->size+1: 1), up(u) {}
+    JSStackNode(JSStackNode *u, int cid) 
+        : ready(false), stop(false), 
+          size(u ? u->size+1: 1), contextid(cid), up(u) {}
     bool ready;
+    bool stop;
     QStringList args;
     int size;
+    int contextid;
     JSStackNode *up;
 };
 
@@ -437,6 +442,10 @@ void KJavaAppletServer::slotJavaRequest(
             cmd = QString::fromLatin1( "resizeapplet" );
             break;
 
         case KJAS_GET_URLDATA:
             //here we need to get some data for a class loader and send it back...
             kdDebug(6100) << "GetURLData from classloader: "<< contextID
@@ -505,7 +514,7 @@ bool KJavaAppletServer::getMember(int co
     args.append( QString::number(objid) );
     args.append( name );
 
-    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
+    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack, contextId);
 
     process->send( KJAS_GET_MEMBER, args );
 
@@ -515,6 +524,7 @@ bool KJavaAppletServer::getMember(int co
     while (!frame->ready && --count > 0) {
         usleep(50000); 
         qApp->processEvents(100);
+        if (frame->stop) return false;
     }
 
     bool retval = frame->ready;
@@ -543,7 +553,7 @@ bool KJavaAppletServer::putMember(int co
     args.append( name );
     args.append( value );
 
-    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
+    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack, contextId);
 
     process->send( KJAS_PUT_MEMBER, args );
 
@@ -552,6 +562,7 @@ bool KJavaAppletServer::putMember(int co
     while (!frame->ready && --count > 0) {
         usleep(50000); 
         qApp->processEvents(100);
+        if (frame->stop) return false;
     }
 
     bool retval = frame->ready;
@@ -576,7 +587,7 @@ bool KJavaAppletServer::callMember(int c
     for (QStringList::const_iterator it = fargs.begin(); it != fargs.end(); it++)
         args.append(*it);
 
-    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
+    JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack, contextId);
 
     process->send( KJAS_CALL_MEMBER, args );
 
@@ -585,6 +596,7 @@ bool KJavaAppletServer::callMember(int c
     while (!frame->ready && --count > 0) {
         usleep(50000); 
         qApp->processEvents(100);
+        if (frame->stop) return false;
     }
 
     bool retval = frame->ready;
@@ -614,4 +626,26 @@ void KJavaAppletServer::derefObject(int 
 
     process->send( KJAS_DEREF_OBJECT, args );
 }
+
+void KJavaAppletServer::stopLiveConnect(int contextId) {
+    int framecount = 0;
+    JSStackNode * frame = d->jsstack;
+    while (frame) {
+        if (frame->contextid == contextId) {
+            frame->stop = true;
+            framecount++;
+        }
+        frame = frame->up;
+    }
+    while (framecount) {
+        qApp->processEvents(100);
+        framecount = 0;
+        frame = d->jsstack;
+        while (frame) {
+            if (frame->contextid == contextId)
+                framecount++;
+            frame = frame->up;
+        }
+    }
+}
+
 #include "kjavaappletserver.moc"
Index: java/kjavaappletcontext.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/kjavaappletcontext.cpp,v
retrieving revision 1.30
diff -u -3 -p -r1.30 kjavaappletcontext.cpp
--- java/kjavaappletcontext.cpp	2002/07/06 02:38:47	1.30
+++ java/kjavaappletcontext.cpp	2002/10/05 14:42:19
@@ -51,6 +51,8 @@ KJavaAppletContext::KJavaAppletContext()
     id = contextCount;
     server->createContext( id, this );
 
+    candoliveconnect = true;
+
     contextCount++;
 }
 
@@ -163,6 +165,22 @@ void KJavaAppletContext::received( const
             tmp->resizeAppletWidget( width, height );
         }
     } 
     else if (cmd.startsWith(QString::fromLatin1("audioclip_"))) {
         kdDebug(6002) << "process Audio command (not yet implemented): " << cmd  << " " << arg[0] << endl;
     }
@@ -193,14 +211,20 @@ void KJavaAppletContext::received( const
 }
 
 bool KJavaAppletContext::getMember(KJavaApplet * applet, const unsigned long objid, const QString & name, int & type, unsigned long & rid, QString & value) {
+    if (!candoliveconnect)
+        return false;
     return server->getMember(id, applet->appletId(), objid, name, type, rid, value);
 }
 
 bool KJavaAppletContext::putMember(KJavaApplet * applet, const unsigned long objid, const QString & name, const QString & value) {
+    if (!candoliveconnect)
+        return false;
     return server->putMember(id, applet->appletId(), objid, name, value);
 }
 
 bool KJavaAppletContext::callMember(KJavaApplet * applet, const unsigned long objid, const QString & name, const QStringList & args, int & type, unsigned long & retobjid, QString & value) {
+    if (!candoliveconnect)
+        return false;
     return server->callMember(id, applet->appletId(), objid, name, args, type, retobjid, value);
 }
 
@@ -208,4 +232,8 @@ void KJavaAppletContext::derefObject(KJa
     server->derefObject(id, applet->appletId(), jid);
 }
 
+void KJavaAppletContext::stopLiveConnect() {
+    candoliveconnect = false;
+    server->stopLiveConnect(id);
+}
 #include <kjavaappletcontext.moc>
Index: java/kjavaappletcontext.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/kjavaappletcontext.h,v
retrieving revision 1.17
diff -u -3 -p -r1.17 kjavaappletcontext.h
--- java/kjavaappletcontext.h	2002/05/25 11:50:27	1.17
+++ java/kjavaappletcontext.h	2002/10/05 14:42:19
@@ -100,6 +100,7 @@ public:
     bool callMember(KJavaApplet *, const unsigned long, const QString &, const QStringList &, int &, unsigned long &, QString &);
     void derefObject(KJavaApplet *, const unsigned long id);
 
+    void stopLiveConnect();
 signals:
     /**
      * Signals the KHMTL Part to show this as the status message.
@@ -124,6 +125,7 @@ protected slots:
 private:
     int id;
     KJavaAppletContextPrivate* d;
+    bool candoliveconnect;
 
 };
 
Index: java/kjavaappletserver.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/kjavaappletserver.h,v
retrieving revision 1.21
diff -u -3 -p -r1.21 kjavaappletserver.h
--- java/kjavaappletserver.h	2002/05/25 11:50:27	1.21
+++ java/kjavaappletserver.h	2002/10/05 14:42:19
@@ -131,6 +131,7 @@ public:
     bool putMember(int contextId, int appletId, const unsigned long, const QString &, const QString &);
     bool callMember(int contextId, int appletId, const unsigned long, const QString &, const QStringList &, int &, unsigned long &, QString &);
     void derefObject(int contextId, int appletId, const unsigned long id);
+    void stopLiveConnect(int contextId);
 protected:
     void setupJava( KJavaProcess* p );
 


More information about the kfm-devel mailing list