Open Bug 909665 Opened 12 years ago Updated 3 years ago

NS_ProcessNextEvent() shouldn't cause fetching next native event while previous native event is being handled

Categories

(Core :: Widget, defect)

x86
Windows 8
defect

Tracking

()

People

(Reporter: masayuki, Unassigned)

References

()

Details

This is the actual cause of bug 907657. nsXMLHttpRequest::Send() calls NS_ProcessNextEvent(). This causes fetching and starting to handle next native event in nsAppShell. In the bug 907657, nsXMLHttpRequest::Send() is called from a keydown event handler. Then, this bug causes handling next WM_CHAR message before DOM keydown event is completely handled (I.e., DOM keypress event is fired during being keydown dispatched!). First, I'm not sure if nsXMLHttpRequest::Send() calls NS_ProcessNextEvent() is correct. Even if it's correct, nsBaseAppShell or nsAppShell shouldn't fetch and start to handle the next native event if the previous event is being handled. I want to add nsXMLHttpRequest folks to CC, however, I don't know who are the good for this bug. Stack: >> xul.dll!mozilla::widget::NativeKey::HandleCharMessage(const tagMSG & aCharMsg, bool * aEventDispatched) Line 932 C++ > xul.dll!nsWindow::ProcessCharMessage(const tagMSG & aMsg, bool * aEventDispatched) Line 5630 + 0xa bytes C++ > xul.dll!nsWindow::ProcessMessage(unsigned int msg, unsigned int & wParam, long & lParam, long * aRetValue) Line 4775 + 0xf bytes C++ > xul.dll!nsWindow::WindowProcInternal(HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 4349 + 0x17 bytes C++ > xul.dll!CallWindowProcCrashProtected(long (HWND__ *, unsigned int, unsigned int, long)* wndProc, HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 32 + 0xf bytes C++ > xul.dll!nsWindow::WindowProc(HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 4301 + 0x14 bytes C++ > user32.dll!771977d8() > [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll] > user32.dll!771978cb() > user32.dll!7719787a() > user32.dll!7719899d() > user32.dll!77198a66() > xul.dll!nsAppShell::ProcessNextNativeEvent(bool mayWait) Line 223 C++ > xul.dll!nsBaseAppShell::DoProcessNextNativeEvent(bool mayWait, unsigned int recursionDepth) Line 137 + 0x16 bytes C++ > xul.dll!nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal * thr, bool mayWait, unsigned int recursionDepth) Line 278 C++ > xul.dll!nsThread::ProcessNextEvent(bool mayWait, bool * result) Line 598 C++ > xul.dll!NS_ProcessNextEvent(nsIThread * thread, bool mayWait) Line 238 + 0xd bytes C++ > xul.dll!nsXMLHttpRequest::Send(nsIVariant * aVariant, const mozilla::dom::Nullable<nsXMLHttpRequest::RequestBody> & aBody) Line 2908 + 0xd bytes C++ > xul.dll!nsXMLHttpRequest::Send(mozilla::ErrorResult & aRv) Line 352 + 0x13 bytes C++ > xul.dll!mozilla::dom::XMLHttpRequestBinding::send(JSContext * cx, JS::Handle<JSObject *> obj, nsXMLHttpRequest * self, const JSJitMethodCallArgs & args) Line 490 C++ > xul.dll!mozilla::dom::XMLHttpRequestBinding::genericMethod(JSContext * cx, unsigned int argc, JS::Value * vp) Line 1167 + 0x20 bytes C++ > mozjs.dll!js::CallJSNative(JSContext * cx, bool (JSContext *, unsigned int, JS::Value *)* native, const JS::CallArgs & args) Line 219 + 0xf bytes C++ > mozjs.dll!js::Invoke(JSContext * cx, JS::CallArgs args, js::MaybeConstruct construct) Line 489 + 0x10 bytes C++ > mozjs.dll!Interpret(JSContext * cx, js::RunState & state) Line 2484 + 0x27 bytes C++ > mozjs.dll!js::RunScript(JSContext * cx, js::RunState & state) Line 446 + 0x7 bytes C++ > mozjs.dll!js::Invoke(JSContext * cx, JS::CallArgs args, js::MaybeConstruct construct) Line 508 + 0xa bytes C++ > mozjs.dll!js::Invoke(JSContext * cx, const JS::Value & thisv, const JS::Value & fval, unsigned int argc, JS::Value * argv, JS::MutableHandle<JS::Value> rval) Line 539 + 0x27 bytes C++ > mozjs.dll!JS_CallFunctionValue(JSContext * cx, JSObject * objArg, JS::Value fval, unsigned int argc, JS::Value * argv, JS::Value * rval) Line 5416 + 0x35 bytes C++ > xul.dll!mozilla::dom::EventHandlerNonNull::Call(JSContext * cx, JS::Handle<JSObject *> aThisObj, nsDOMEvent & event, mozilla::ErrorResult & aRv) Line 38 + 0x2d bytes C++ > xul.dll!mozilla::dom::EventHandlerNonNull::Call<nsISupports *>(nsISupports * const & thisObj, nsDOMEvent & event, mozilla::ErrorResult & aRv, mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling) Line 59 + 0x21 bytes C++ > xul.dll!nsJSEventListener::HandleEvent(nsIDOMEvent * aEvent) Line 249 C++ > xul.dll!nsEventListenerManager::HandleEventSubType(nsListenerStruct * aListenerStruct, const mozilla::dom::CallbackObjectHolder<mozilla::dom::EventListener,nsIDOMEventListener> & aListener, nsIDOMEvent * aDOMEvent, mozilla::dom::EventTarget * aCurrentTarget, nsCxPusher * aPusher) Line 977 + 0x10 bytes C++ > xul.dll!nsEventListenerManager::HandleEventInternal(nsPresContext * aPresContext, nsEvent * aEvent, nsIDOMEvent * * aDOMEvent, mozilla::dom::EventTarget * aCurrentTarget, nsEventStatus * aEventStatus, nsCxPusher * aPusher) Line 1049 + 0x12 bytes C++ > xul.dll!nsEventListenerManager::HandleEvent(nsPresContext * aPresContext, nsEvent * aEvent, nsIDOMEvent * * aDOMEvent, mozilla::dom::EventTarget * aCurrentTarget, nsEventStatus * aEventStatus, nsCxPusher * aPusher) Line 330 + 0x15 bytes C++ > xul.dll!nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor & aVisitor, ELMCreationDetector & aCd, nsCxPusher * aPusher) Line 188 C++ > xul.dll!nsEventTargetChainItem::HandleEventTargetChain(nsTArray<nsEventTargetChainItem> & aChain, nsEventChainPostVisitor & aVisitor, nsDispatchingCallback * aCallback, ELMCreationDetector & aCd, nsCxPusher * aPusher) Line 284 C++ > xul.dll!nsEventDispatcher::Dispatch(nsISupports * aTarget, nsPresContext * aPresContext, nsEvent * aEvent, nsIDOMEvent * aDOMEvent, nsEventStatus * aEventStatus, nsDispatchingCallback * aCallback, nsCOMArray<mozilla::dom::EventTarget> * aTargets) Line 585 C++ > xul.dll!PresShell::HandleEventInternal(nsEvent * aEvent, nsEventStatus * aStatus) Line 6861 + 0x14 bytes C++ > xul.dll!PresShell::HandleEvent(nsIFrame * aFrame, nsGUIEvent * aEvent, bool aDontRetargetEvents, nsEventStatus * aEventStatus) Line 6444 + 0xd bytes C++ > xul.dll!PresShell::HandleEvent(nsIFrame * aFrame, nsGUIEvent * aEvent, bool aDontRetargetEvents, nsEventStatus * aEventStatus) Line 6042 + 0x19 bytes C++ > xul.dll!nsViewManager::DispatchEvent(nsGUIEvent * aEvent, nsView * aView, nsEventStatus * aStatus) Line 741 C++ > xul.dll!nsView::HandleEvent(nsGUIEvent * aEvent, bool aUseAttachedEvents) Line 1084 C++ > xul.dll!nsWindow::DispatchEvent(nsGUIEvent * event, nsEventStatus & aStatus) Line 3611 + 0x10 bytes C++ > xul.dll!nsWindow::DispatchWindowEvent(nsGUIEvent * event) Line 3635 C++ > xul.dll!mozilla::widget::NativeKey::DispatchKeyEvent(nsKeyEvent & aKeyEvent, const tagMSG * aMsgSentToPlugin) Line 800 + 0x12 bytes C++ > xul.dll!mozilla::widget::NativeKey::HandleKeyDownMessage(bool * aEventDispatched) Line 829 C++ > xul.dll!nsWindow::ProcessKeyDownMessage(const tagMSG & aMsg, bool * aEventDispatched) Line 5660 + 0x9 bytes C++ > xul.dll!nsWindow::ProcessMessage(unsigned int msg, unsigned int & wParam, long & lParam, long * aRetValue) Line 4797 C++ > xul.dll!nsWindow::WindowProcInternal(HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 4349 + 0x17 bytes C++ > xul.dll!CallWindowProcCrashProtected(long (HWND__ *, unsigned int, unsigned int, long)* wndProc, HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 32 + 0xf bytes C++ > xul.dll!nsWindow::WindowProc(HWND__ * hWnd, unsigned int msg, unsigned int wParam, long lParam) Line 4301 + 0x14 bytes C++ > user32.dll!771977d8() > user32.dll!771978cb() > user32.dll!7719787a() > user32.dll!7719899d() > user32.dll!771a55c6() > user32.dll!77198a66() > xul.dll!nsAppShell::ProcessNextNativeEvent(bool mayWait) Line 223 C++ > xul.dll!nsBaseAppShell::DoProcessNextNativeEvent(bool mayWait, unsigned int recursionDepth) Line 137 + 0x16 bytes C++ > xul.dll!nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal * thr, bool mayWait, unsigned int recursionDepth) Line 278 C++ > xul.dll!nsThread::ProcessNextEvent(bool mayWait, bool * result) Line 598 C++ > xul.dll!NS_ProcessNextEvent(nsIThread * thread, bool mayWait) Line 238 + 0xd bytes C++ > xul.dll!mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate * aDelegate) Line 81 + 0xa bytes C++ > xul.dll!MessageLoop::RunInternal() Line 220 + 0x9 bytes C++ > xul.dll!MessageLoop::RunHandler() Line 214 C++ > xul.dll!MessageLoop::Run() Line 188 C++ > xul.dll!nsBaseAppShell::Run() Line 163 C++ > xul.dll!nsAppShell::Run() Line 112 + 0x8 bytes C++ > xul.dll!nsAppStartup::Run() Line 270 C++ > xul.dll!XREMain::XRE_mainRun() Line 3871 + 0xe bytes C++ > xul.dll!XREMain::XRE_main(int argc, char * * argv, const nsXREAppData * aAppData) Line 3939 + 0x7 bytes C++ > xul.dll!XRE_main(int argc, char * * argv, const nsXREAppData * aAppData, unsigned int aFlags) Line 4152 + 0x12 bytes C++ > firefox.exe!do_main(int argc, char * * argv, nsIFile * xreDirectory) Line 275 + 0x1d bytes C++ > firefox.exe!NS_internal_main(int argc, char * * argv) Line 635 + 0xd bytes C++ > firefox.exe!wmain(int argc, wchar_t * * argv) Line 112 C++ > firefox.exe!__tmainCRTStartup() Line 552 + 0x19 bytes C > firefox.exe!wmainCRTStartup() Line 371 C > kernel32.dll!774f850d() > ntdll.dll!77d7bf39() > ntdll.dll!77d7bf0c() The HandleCharMessage() is called while HandleKeyDownMessage() is dispatching keydown message!! URL is the testcase for this. Press a key on the <input> element.
Summary: NS_ProcessNextEvent() shouldn't cause fetching next native event while previous native event is handling → NS_ProcessNextEvent() shouldn't cause fetching next native event while previous native event is being handled
Well, we don't have anything better. We need to be able to spin event loop and get both Gecko events (runnables) and OS events working while we're executing sync XHR. Otherwise we block the whole UI. Also, we do use NS_ProcessNextEvent() in other similar cases where we do some sort of sync call. alert/showModalDialog etc.
Well, modal dialog case is a difficult problem, but I don't feel so for XHR. Is it impossible to ignore OS event at that time?
We must handle OS events at that time. Otherwise browser chrome is blocked, and we want to block only JS in web pages.
This is very similar to metro bug 907410, where we've run into the same problem. A loop like this will freeze the metro browser since the dispatch method we use refuses to process any events if the dispatcher is on the stack. dispatch loops like this in our code need to go away.
Then we need some layer between Win8 OS level events and Gecko so that OS events enter Gecko asynchronously from OS point of view.
(In reply to Olli Pettay [:smaug] from comment #5) > Then we need some layer between Win8 OS level events and Gecko so that OS > events enter Gecko > asynchronously from OS point of view. Yep, putting content in another process is the long term solution. For now we're stuck with ugly hacks with lots of potential negative side effects.
I don't know what is ugly with handling OS level events async. That is what would happen in e10s' content processes anyway.
(In reply to Olli Pettay [:smaug] from comment #3) > We must handle OS events at that time. Otherwise browser chrome is blocked, > and we want to > block only JS in web pages. Indeed. I have additional question. Should DOM events be not fired on contents? I mean DOM events should be fired only on Chrome or system event group at that time?
We queue certain events which fire on content when we're processing sync XHR. That mechanism works reasonable well, usually.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.