KJS CPU Guard locks konqueror

Koos Vriezen koos.vriezen at xs4all.nl
Mon Sep 1 14:47:01 BST 2003


On Sun, 31 Aug 2003, Koos Vriezen wrote:

> On Sat, 30 Aug 2003, David Faure wrote:
>
> > On a page with a long JS execution (I had KJS_VERBOSE enabled), konqueror hanged.
> > Apparently, doing a malloc from an alarm handler is only good for getting a deadlock.
>
> If so, we would have more reports about it no? But it can happen
> indeed..the only thing save in this handler is
> 'ExecState::requestTerminate()' so maybe the KMessageBox::warningYesNo
> should go to kjs when it detects a previous ExecState::requestTerminate()
> call.

Here it is. I must say I hate it, but it's the only thing I could think
of.

Koos

> > (gdb) bt
> > #0  0x413f3fb5 in nanosleep () from /lib/i686/libpthread.so.0
> > #1  0x4096b85e in lock (m=0x40) at /mnt/devel/kde/kdecvs/kdelibs/kdecore/malloc/x86.h:32
> > #2  0x40969a5b in malloc (bytes=64) at /mnt/devel/kde/kdecvs/kdelibs/kdecore/malloc/malloc.c:5511
> > #3  0x414ea37e in operator new(unsigned) () from /usr/lib/libstdc++.so.5
> > #4  0x414ea4ad in operator new[](unsigned) () from /usr/lib/libstdc++.so.5
> > #5  0x41019f02 in QString::setLength(unsigned) (this=0xbfffcd30, newLen=24) at qstring.cpp:1677
> > #6  0x4102122e in QString::fromUtf8(char const*, int) (utf8=0x41bfbd3a "alarmhandler", len=12) at qstring.cpp:5265
> > #7  0x40191c25 in kdbgstream::operator<<(char const*) (this=0xbfffce20, string=0x41bfbd3a "alarmhandler") at kdebug.h:199
> > #8  0x41b78a8d in KJSCPUGuard::alarmHandler(int) () at /mnt/devel/kde/kdecvs/kdelibs/khtml/ecma/kjs_proxy.cpp:395
> > #9  0x413f35ce in __pthread_sighandler () from /lib/i686/libpthread.so.0
> > #10 0x415653b8 in __libc_sigaction () from /lib/i686/libc.so.6
> > #11 0x40969a76 in malloc (bytes=128) at /mnt/devel/kde/kdecvs/kdelibs/kdecore/malloc/malloc.c:5514
> > #12 0x414ea37e in operator new(unsigned) () from /usr/lib/libstdc++.so.5
> > #13 0x414ea4ad in operator new[](unsigned) () from /usr/lib/libstdc++.so.5
> > #14 0x41019f02 in QString::setLength(unsigned) (this=0xbfffd320, newLen=40) at qstring.cpp:1677
> > #15 0x4102122e in QString::fromUtf8(char const*, int) (utf8=0x41bf6981 "DOMNodeList::tryGet ", len=20) at qstring.cpp:5265
> > #16 0x40191c25 in kdbgstream::operator<<(char const*) (this=0xbfffd470, string=0x41bf6981 "DOMNodeList::tryGet ")
> >     at /mnt/devel/kde/kdecvs/kdelibs/kdecore/kdebug.h:199
> > #17 0x41b1f1e0 in KJS::DOMNodeList::tryGet(KJS::ExecState*, KJS::Identifier const&) const (this=0x85d1430, exec=0xbfffdc20, p=@0xbfffd560)
> >     at /mnt/devel/kde/kdecvs/kdelibs/khtml/ecma/kjs_dom.cpp:603
> > #18 0x41b17156 in KJS::DOMObject::get(KJS::ExecState*, KJS::Identifier const&) const (this=0x85d1430, exec=0xbfffdc20, p=@0xbfffd560)
> >     at /mnt/devel/kde/kdecvs/kdelibs/khtml/ecma/kjs_binding.cpp:48
> > #19 0x41ce216f in KJS::ObjectImp::get(KJS::ExecState*, unsigned) const (this=0x85d1430, exec=0xbfffdc20, propertyName=148)
> >     at /mnt/devel/kde/kdecvs/kdelibs/kjs/object.cpp:186
> > #20 0x41ce9760 in KJS::Reference::getValue(KJS::ExecState*) const (this=0xbfffd600, exec=0xbfffdc20) at /mnt/devel/kde/kdecvs/kdelibs/kjs/reference.cpp:141
> > #21 0x41ca60a3 in KJS::Node::evaluate(KJS::ExecState*) const (this=0x85e95b8, exec=0xbfffdc20) at /mnt/devel/kde/kdecvs/kdelibs/kjs/nodes.cpp:122
> >
> > The signal happened while we were in a malloc, and apparently there is a
> > lock there, i.e. it's not reentrant.
> >
> > There is no way we can show a dialog from a signal handler, there is always going
> > to be a malloc around...
> >
> > I just talked to Lars about this, and his suggestion is: set a flag in the signal handler,
> > and check for that flag regularly inside KJS (not sure where exactly). This
> > seems to be the only solution to prevent such deadlocks.
> > Koos: what do you think?
> >
> > --
> > David FAURE, faure at kde.org, sponsored by Trolltech to work on KDE,
> > Konqueror (http://www.konqueror.org), and KOffice (http://www.koffice.org).
> >
>
-------------- next part --------------
Index: khtml/ecma/kjs_proxy.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/ecma/kjs_proxy.h,v
retrieving revision 1.26
diff -u -3 -p -r1.26 kjs_proxy.h
--- khtml/ecma/kjs_proxy.h	17 May 2003 22:12:57 -0000	1.26
+++ khtml/ecma/kjs_proxy.h	1 Sep 2003 13:36:14 -0000
@@ -79,6 +79,7 @@ public:
 private:
   void (*oldAlarmHandler)(int);
   static void alarmHandler(int);
+  static bool confirmTerminate();
   itimerval oldtv; 
 };
 
Index: khtml/ecma/kjs_proxy.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/ecma/kjs_proxy.cpp,v
retrieving revision 1.107
diff -u -3 -p -r1.107 kjs_proxy.cpp
--- khtml/ecma/kjs_proxy.cpp	25 Jun 2003 22:32:14 -0000	1.107
+++ khtml/ecma/kjs_proxy.cpp	1 Sep 2003 13:36:14 -0000
@@ -391,8 +391,12 @@ void KJSCPUGuard::stop()
   signal(SIGVTALRM, oldAlarmHandler);
 }
 
-void KJSCPUGuard::alarmHandler(int) {
+bool KJSCPUGuard::confirmTerminate() {
   kdDebug(6070) << "alarmhandler" << endl;
-  if (KMessageBox::warningYesNo(0L, i18n("A script on this page is causing KHTML to freeze. If it continues to run, other applications may become less responsive.\nDo you want to abort the script?"), i18n("JavaScript"), i18n("Abort"), KStdGuiItem::cont(), "kjscupguard_alarmhandler") == KMessageBox::Yes)
+  return KMessageBox::warningYesNo(0L, i18n("A script on this page is causing KHTML to freeze. If it continues to run, other applications may become less responsive.\nDo you want to abort the script?"), i18n("JavaScript"), i18n("Abort"), KStdGuiItem::cont(), "kjscupguard_alarmhandler") == KMessageBox::Yes;
+}
+
+void KJSCPUGuard::alarmHandler(int) {
     ExecState::requestTerminate();
+    ExecState::confirmTerminate = KJSCPUGuard::confirmTerminate;
 }
Index: kjs/interpreter.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/interpreter.cpp,v
retrieving revision 1.22
diff -u -3 -p -r1.22 interpreter.cpp
--- kjs/interpreter.cpp	8 Mar 2003 12:32:22 -0000	1.22
+++ kjs/interpreter.cpp	1 Sep 2003 13:36:14 -0000
@@ -369,10 +369,17 @@ void ExecState::clearException()
 
 bool ExecState::terminate_request = false;
 
+static bool defaultConfirm() { return true; }
+
+bool (*ExecState::confirmTerminate)() = defaultConfirm;
+
 bool ExecState::hadException()
 {
-  if (terminate_request)
-    _exception = Error::create((ExecState*)this);
+  if (terminate_request) {
+    if (confirmTerminate())
+      _exception = Error::create((ExecState*)this);
+    terminate_request = false;
+  }
   return _exception.isValid();
 }
 
Index: kjs/interpreter.h
===================================================================
RCS file: /home/kde/kdelibs/kjs/interpreter.h,v
retrieving revision 1.22
diff -u -3 -p -r1.22 interpreter.h
--- kjs/interpreter.h	16 Aug 2003 19:45:12 -0000	1.22
+++ kjs/interpreter.h	1 Sep 2003 13:36:15 -0000
@@ -457,6 +457,10 @@ namespace KJS {
      * request for ending execution with an exception
      */
     static void requestTerminate() { terminate_request = true; }
+    /*
+     * optional confirmation for ending execution after requestTerminate()
+     */
+    static bool (*confirmTerminate)();
   private:
     ExecState(Interpreter *interp, ContextImp *con)
         : _interpreter(interp), _context(con) { }


More information about the kfm-devel mailing list