yueying0083 / javachromiumembedded

Automatically exported from code.google.com/p/javachromiumembedded
0 stars 0 forks source link

Introduces a state model for CefApp and fixed the CMD+Q issue on Mac #105

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Use latest SVN-Trunk (r99)
2. Create and dispose a CefBrowser instance several times
3. Shutdown application

What is the expected output? What do you see instead?
1. The application should dispose all CefBrowser instances and close all Helper 
processes
Instead the CefBrowser is removed from the screen, 
CefLifeSpanHandler.doClose(CefBrowser browser) is invoked
but CefLifeSpanHandler.onBeforeClose(CefBrowser browser) is only invoked if you 
close your app, not if you dispose a CefBrowser.
2. In some cases the application crashes because not every reference was 
removed in the native code
3. On Mac: Pressing CMD-Q causes a crash on exit of the app
3. If you call System.exit(0) too early, your app will crash instead of 
shutting down without a crash

What version of the product are you using? On what operating system?
Latest SVN-Trunk (r99)

Please provide any additional information below.
==> Please see my attached patch file "2014-07-25_fixed_shutdown.patch" for a 
solution of this issue.

Most significant changes in the patch file:
-------------------------------------------
(*) Fixed that CefLifeSpanHandler.onBeforeClose() isn't called at the right 
time.
(*) Introduced 6 states which tells you in which mood CefApp currently is. All 
state changes are reported by the new Method 
CefAppHandler.stateHasChanged(state).
The attached image "StateDiagram-CefApp.jpg" describes those states and which 
method call on CefApp changes the state and its lifecycle.
(*) The lifecycle of CefApp has changed in several points:
     1) For Mac: Introduced a shutdown hook to quit the application if System.exit(0) is called before CefShutdown() is finished.
     2) Calling dispose() will send a dispose() to all CefClient instances. The message loop is kept running until all CefClient and all CefBrowser instances have been disposed.
     3) a) CefClient sends a dispose to all CefBrowser instances.
        b) If all CefBrowser instances responded with CefLifeSpanHandler.onBeforeClose(), CefClient sends a "clientWasDisposed()" to CefApp and destroys itself.
     4) If CefApp has received "clientWasDisposed()" for all CefClients, it terminates the message Loop and sends an "CefShutdown()" to the native code.
     4) After CefApp has send a CefAppHandler.stateHasChanged(TERMINATED), the Java application can be shutdown safely.

Native changes to fix the QMD-Q issue on Mac:
(*) Moved the class ClientApp to its own files (cpp & h) 
(*) For Mac only: Added a swizzled "terminate" method to hook into the CMD+Q 
call
    1) If this is called, the ClientApp informs the Java class CefApp. That the user wants to shut down
    2) CefApp asks the user by calling CefAppHandler.onBeforeTerminate() if it should proceed with the shutdown
    3) If the user returns false, all Java instances and native instances are disposed and cleaned up. Afterwards the native "terminate" method is executed.
       If the user returs true, the "terminate" method is suppressed.

Original issue reported on code.google.com by k...@censhare.de on 25 Jul 2014 at 10:10

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by k...@censhare.de on 25 Jul 2014 at 10:38

Attachments:

GoogleCodeExporter commented 9 years ago
This patch fixes issue 97 as well.

Original comment by k...@censhare.de on 25 Jul 2014 at 10:55

GoogleCodeExporter commented 9 years ago
Issue 97 has been merged into this issue.

Original comment by magreenb...@gmail.com on 29 Jul 2014 at 10:32

GoogleCodeExporter commented 9 years ago
This change is causing a crash/hang during shutdown() (CefApp.java) on Windows 
8.1. The native code never returns from the call to CefShutdown(). It seems 
like maybe the window hasn't completely destructed before CefShutdown() is 
called even though OnBeforeClose() has been executed for the CefBrowser 
instance. Here's the call stack:

    libcef.dll!logging::LogMessage::~LogMessage() Line 564  C++
    libcef.dll!aura::Env::GetInstance() Line 57 C++
    libcef.dll!wm::ShadowController::Impl::~Impl() Line 243 C++
    [External Code] 
    libcef.dll!base::RefCounted<wm::ShadowController::Impl>::Release() Line 131 C++
    libcef.dll!scoped_refptr<wm::ShadowController::Impl>::~scoped_refptr<wm::ShadowController::Impl>() Line 290 C++
    libcef.dll!wm::ShadowController::~ShadowController() Line 259   C++
    [External Code] 
    libcef.dll!base::DefaultDeleter<wm::ShadowController>::operator()(wm::ShadowController * ptr) Line 137  C++
    libcef.dll!base::internal::scoped_ptr_impl<wm::ShadowController,base::DefaultDeleter<wm::ShadowController> >::reset(wm::ShadowController * p) Line 247  C++
    libcef.dll!scoped_ptr<wm::ShadowController,base::DefaultDeleter<wm::ShadowController> >::reset(wm::ShadowController * p) Line 367   C++
    libcef.dll!views::DesktopNativeWidgetAura::OnHostClosed() Line 297  C++
    libcef.dll!views::DesktopWindowTreeHostWin::HandleDestroyed() Line 783  C++
    libcef.dll!views::HWNDMessageHandler::OnWndProc(unsigned int message, unsigned __int64 w_param, __int64 l_param) Line 913   C++
>   libcef.dll!gfx::WindowImpl::WndProc(HWND__ * hwnd, unsigned int message, 
unsigned __int64 w_param, __int64 l_param) Line 268 C++
    libcef.dll!base::win::WrappedWindowProc<&gfx::WindowImpl::WndProc>(HWND__ * hwnd, unsigned int message, unsigned __int64 wparam, __int64 lparam) Line 76    C++
    [External Code] 
    libcef.dll!base::DeleteFileW(const base::FilePath & path, bool recursive) Line 81   C++
    libcef.dll!base::ScopedTempDir::Delete() Line 64    C++
    libcef.dll!base::ScopedTempDir::~ScopedTempDir() Line 16    C++
    libcef.dll!CefContext::~CefContext() Line 221   C++
    [External Code] 
    libcef.dll!CefShutdown() Line 144   C++
    libcef.dll!cef_shutdown() Line 179  C++
    jcef.dll!CefShutdown() Line 171 C++
    jcef.dll!Java_org_cef_CefApp_N_1Shutdown(JNIEnv_ * env, _jobject * __formal) Line 108   C++

Original comment by magreenb...@gmail.com on 20 Aug 2014 at 2:40

GoogleCodeExporter commented 9 years ago
@#4: The problem does not reproduce on Windows 7 and seems unrelated to the 
Java version (tested with both 7u51 and 7u67).

Original comment by magreenb...@gmail.com on 9 Sep 2014 at 5:14

GoogleCodeExporter commented 9 years ago
@#4: The fix appears to be calling N_DoMessageLoopWork() one final time before 
calling N_Shutdown() in CefApp.shutdown(). We were doing that in the 
implementation of CefApp.run() that existed before this patch.

Committed in revision 101.

Original comment by magreenb...@gmail.com on 9 Sep 2014 at 9:22