Patch: Crash: blocking JS alert and deleting a window
Koos Vriezen
koos.vriezen at xs4all.nl
Sat Oct 19 13:19:49 BST 2002
On Sat, 19 Oct 2002, David Faure wrote:
> On Friday 18 October 2002 23:18, Koos Vriezen wrote:
> > Unfortunately removing topLevelWidget() in ecma/kjs_window makes
> > 'setTimeout('self.close()',1000); alert("Hi");' crash again, better leave
> > it then
>
> Hmm, why? Message boxes created by Window::Alert use the
> KHTMLView as parent widget, and there's only one khtmlview in this case......
>
> (or are you talking about the testcase that used window.open?)
Turns out removing topLevelWidget() does work, but changing hide() for
close() does reintroduce the crash. Not sure why,
QWidget::close(bool alsoDelete) calls QApplication::sendEvent(this, &e), e
being QCloseEvent, QDialog::closeEvent(QCloseEvent *e) calls reject() that
calls done(int r) which calls hide(). QApplication::sendEvent does call
QDialog::closeEvent without reschedule, no?
Hmmm, (qt-copy/src/kernel/qwidget.cpp:3944)
QApplication::sendEvent( this, &e );
deleted = !QWidget::find(id);
if ( !deleted && !e.isAccepted() ) {
is_closing = 0;
return FALSE;
}
if ( !deleted )
hide();
does QWidget::find return false here.
> > (can JS close a frame?).
>
> Not a frame, but a Konqueror view in a splitted window.
> Let me detail this:
> those two setups are very different:
> * One KHTMLPart in the Konqueror view, with frames inside
> * A splitted Konqueror window (using Konqueror's Split options),
> with two KHTMLParts.
> In the latter case, it's really like having two windows side by side.
> window.close() should only destroy one of the views (I believe this
> works).
Yes, indeed.
> > +void KHTMLView::closeChildDialogs()
> > +{
> > + QObjectList *dlgs = queryList("QDialog");
> > + for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
> > + static_cast<QWidget*>(dlg)->close();
> > + delete dlgs;
> > }
>
> I prefer that one, who knows if we won't have to call it from
> another place.
Yes, later I thought having a central place for this, can be usefull for
not deleting dialogs not created by JS (eg. the find dialog).
> Dirk wrote:
> > Am I the only one who is scared like hell when I see such code ?
>
> Yes, well, obviously Qt wasn't designed with this (very unusual) case in mind.
> Do you know any other app where a window or widget pops up a modal dialog,
> and then, before the user selects something in it, the window or widget is being
> destroyed? The "enter_loop" done by the modal dialog has to be exited at
> the right time - which isn't in the QWidget destructor of the parent (it's far too late,
> the control will go back into the code of the deleted widget).
Yes, additional look at the stack:
<html><head><script>
setTimeout('self.close()',1000);alert(somevar);
</script></head><body></body></html>
0 main_message_loop
1 ..
2 tokenizer execute JS
3 KMessageBox::exec
4 dialog_message_loop
5 timer event
6 KHTMLPart::~KHTMLPart -> delete m_view -> closes child dialogs
7 KHTMLPart::clear -> KJSProxy::clear() -> DocumentImpl::detach
If the stack pops back, a crash occurs in the tokenizer because everyting
is deleted. Doing a hide() makes QDialog::in_loop become FALSE, so it
return from 4 and 3, which makes 2 being able to finish before
KHTMLPart::~KHTMLPart is called.
> Dirk also wrote:
> > you actually have to revert a workaround I committed yesterday to avoid the
> > crash..
> Koos: I believe this is about the !mimeName.isEmpty() in render_frames.cpp:811.
Ok reverted that. Indeed I get an do-you-want-to-download-xxx message
box, but only one and clicking no doesn't make it crash.
Koos
More information about the kfm-devel
mailing list