From aca556ce936f3967e8dcc017b0d9279951897d18 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Thu, 12 Jan 2017 14:52:13 +0900 Subject: [PATCH] Locate ewk_view_page_close in extended main loop Sometimes, closing page callbkack is missing when the callback comes between terminating main loop and creating extended main loop. In that case, deadlock situation happens. To avoid the issue, the ewk_view_page_close needs to be called in extended main loop to assure receiving the callback. Also, evas object needs to be deleted when it's valid. Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2782 Change-Id: I7a86121bc7c78225b54bb6fe22b934f62615a46d Signed-off-by: Youngsoo Choi --- runtime/browser/ime_runtime.cc | 5 ++++- runtime/browser/ime_runtime.h | 1 + runtime/browser/runtime.cc | 25 ++++++++++++++++++++++--- runtime/browser/runtime.h | 11 ++++++++++- runtime/browser/runtime_process.cc | 11 ++--------- runtime/browser/ui_runtime.cc | 6 +++++- runtime/browser/ui_runtime.h | 1 + runtime/browser/watch_runtime.cc | 5 ++++- runtime/browser/watch_runtime.h | 1 + runtime/browser/web_application.cc | 31 +++++++++++++++++++++++-------- runtime/browser/web_application.h | 2 +- runtime/browser/web_view_impl.cc | 1 + 12 files changed, 75 insertions(+), 25 deletions(-) diff --git a/runtime/browser/ime_runtime.cc b/runtime/browser/ime_runtime.cc index 0527c83..78a890a 100644 --- a/runtime/browser/ime_runtime.cc +++ b/runtime/browser/ime_runtime.cc @@ -163,8 +163,11 @@ void ImeRuntime::OnCreate() { } void ImeRuntime::OnTerminate() { +} + +void ImeRuntime::Terminate() { LOGGER(DEBUG) << "ime_app_terminate"; - ClosePageFromOnTerminate(application_); + ProcessClosingPage(application_); } void ImeRuntime::OnShow(int context_id, ime_context_h context) { diff --git a/runtime/browser/ime_runtime.h b/runtime/browser/ime_runtime.h index 1284a3d..b020539 100644 --- a/runtime/browser/ime_runtime.h +++ b/runtime/browser/ime_runtime.h @@ -42,6 +42,7 @@ class ImeRuntime : public Runtime { virtual void OnHide(int context_id); virtual void OnAppControl(); + virtual void Terminate(); private: WebApplication* application_; NativeWindow* native_window_; diff --git a/runtime/browser/runtime.cc b/runtime/browser/runtime.cc index 4298837..5861b08 100644 --- a/runtime/browser/runtime.cc +++ b/runtime/browser/runtime.cc @@ -20,6 +20,7 @@ #include "common/application_data.h" #include "common/command_line.h" +#include "common/logger.h" #include "runtime/common/constants.h" #include "runtime/browser/runtime.h" #include "runtime/browser/ui_runtime.h" @@ -30,6 +31,8 @@ #include "runtime/browser/watch_runtime.h" #endif // WATCH_FACE_FEATURE_SUPPORT +#define MAIN_LOOP_INTERVAL 1 + namespace runtime { Runtime::~Runtime() { @@ -55,9 +58,25 @@ std::unique_ptr Runtime::MakeRuntime( } } -void Runtime::ClosePageFromOnTerminate(WebApplication* app) { - if (app) - app->ClosePageFromOnTerminate(); +// static +Eina_Bool Runtime::ClosePageInExtendedMainLoop(void* user_data) +{ + LOGGER(DEBUG); + struct Timer* main_loop = static_cast(user_data); + main_loop->application->ClosePage(); + return ECORE_CALLBACK_CANCEL; +} + +void Runtime::ProcessClosingPage(WebApplication* application) { + LOGGER(DEBUG); + if (application) { + struct Timer main_loop; + main_loop.application = application; + main_loop.timer = ecore_timer_add(MAIN_LOOP_INTERVAL, ClosePageInExtendedMainLoop, &main_loop); + LOGGER(DEBUG) << "Defer termination of main loop"; + ecore_main_loop_begin(); + ecore_timer_del(main_loop.timer); + } } } // namespace runtime diff --git a/runtime/browser/runtime.h b/runtime/browser/runtime.h index 00dea07..63ddc97 100755 --- a/runtime/browser/runtime.h +++ b/runtime/browser/runtime.h @@ -29,6 +29,7 @@ namespace runtime { class Runtime { public: virtual ~Runtime() = 0; + virtual void Terminate() = 0; virtual int Exec(int argc, char* argv[]) = 0; @@ -36,7 +37,15 @@ class Runtime { common::ApplicationData* app_data); protected: - void ClosePageFromOnTerminate(WebApplication* app); + void ProcessClosingPage(WebApplication* application); + + private: + static Eina_Bool ClosePageInExtendedMainLoop(void* user_data); + struct Timer + { + WebApplication* application; + Ecore_Timer* timer; + }; }; } // namespace runtime diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 83d7645..757fdfa 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -128,20 +128,13 @@ int real_main(int argc, char* argv[]) { #endif // WATCH_FACE_FEATURE_SUPPORT } - int ret = 0; // Runtime's destructor should be called before ewk_shutdown() { std::unique_ptr runtime = runtime::Runtime::MakeRuntime(appdata); - ret = runtime->Exec(argc, argv); - if (ret) + if (runtime->Exec(argc, argv)) LOGGER(ERROR) << "Exec returns non zero."; - LOGGER(DEBUG) << "plugin_session_count : " << - XWalkExtensionRendererController::plugin_session_count; - if (XWalkExtensionRendererController::plugin_session_count > 0) { - LOGGER(DEBUG) << "Defer termination of main loop"; - ecore_main_loop_begin(); - } + runtime->Terminate(); runtime.reset(); } LOGGER(DEBUG) << "ewk_shutdown"; diff --git a/runtime/browser/ui_runtime.cc b/runtime/browser/ui_runtime.cc index 4e20943..41fa8d9 100755 --- a/runtime/browser/ui_runtime.cc +++ b/runtime/browser/ui_runtime.cc @@ -142,7 +142,11 @@ bool UiRuntime::OnCreate() { } void UiRuntime::OnTerminate() { - ClosePageFromOnTerminate(application_.get()); +} + +void UiRuntime::Terminate() { + LOGGER(DEBUG); + ProcessClosingPage(application_.get()); } void UiRuntime::OnPause() { diff --git a/runtime/browser/ui_runtime.h b/runtime/browser/ui_runtime.h index 7aff1f7..1625abd 100644 --- a/runtime/browser/ui_runtime.h +++ b/runtime/browser/ui_runtime.h @@ -44,6 +44,7 @@ class UiRuntime : public Runtime { virtual void OnAppControl(app_control_h app_control); virtual void OnLanguageChanged(const std::string& language); virtual void OnLowMemory(); + virtual void Terminate(); private: void ResetWebApplication(NativeWindow::Type windowType); diff --git a/runtime/browser/watch_runtime.cc b/runtime/browser/watch_runtime.cc index 657a7f1..f166e72 100644 --- a/runtime/browser/watch_runtime.cc +++ b/runtime/browser/watch_runtime.cc @@ -99,7 +99,10 @@ bool WatchRuntime::OnCreate() { } void WatchRuntime::OnTerminate() { - ClosePageFromOnTerminate(application_); +} + +void WatchRuntime::Terminate() { + ProcessClosingPage(application_); } void WatchRuntime::OnPause() { diff --git a/runtime/browser/watch_runtime.h b/runtime/browser/watch_runtime.h index 94c23d2..7fd5c3a 100644 --- a/runtime/browser/watch_runtime.h +++ b/runtime/browser/watch_runtime.h @@ -46,6 +46,7 @@ class WatchRuntime : public Runtime { virtual void OnAmbientTick(watch_time_h watch_time); virtual void OnAmbientChanged(bool ambient_mode); + virtual void Terminate(); private: WebApplication* application_; NativeWindow* native_window_; diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index e0ef6a5..e11d9e0 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -659,15 +659,33 @@ void WebApplication::Terminate() { extension_server->Shutdown(); } -void WebApplication::ClosePageFromOnTerminate() { +void WebApplication::ClosePage() { LOGGER(DEBUG); + int valid_evas_object_count = 0; auto it = view_stack_.begin(); if (it != view_stack_.end()) { for (; it != view_stack_.end(); ++it) { (*it)->ReplyToJavascriptDialog(); view_stack_.front()->SetVisibility(false); - LOGGER(DEBUG) << "ewk_view_page_close"; - ewk_view_page_close((*it)->evas_object()); + if (ewk_view_page_close((*it)->evas_object())) { + LOGGER(DEBUG) << "ewk_view_page_close returns true"; + valid_evas_object_count++; + } else { + LOGGER(DEBUG) << "ewk_view_page_close returns false"; + } + } + } + if (valid_evas_object_count == 0) { + if (is_terminate_called_) { + ecore_main_loop_quit(); + } else { + if (terminator_) { + LOGGER(DEBUG) << "terminator_"; + terminator_(); + } else { + LOGGER(ERROR) << "There's no registered terminator."; + elm_exit(); + } } } } @@ -759,11 +777,8 @@ void WebApplication::OnClosedWebView(WebView* view) { LOGGER(DEBUG) << "plugin_session_count : " << XWalkExtensionRendererController::plugin_session_count; - if (XWalkExtensionRendererController::plugin_session_count > 0) { - timeout_id = ecore_timer_add(TIMER_INTERVAL, CheckPluginSession, this); - if (!timeout_id) - LOGGER(ERROR) << "It's failed to create timer"; - } + if (!ecore_timer_add(TIMER_INTERVAL, CheckPluginSession, this)) + LOGGER(ERROR) << "It's failed to create timer"; } void WebApplication::OnReceivedWrtMessage(WebView* view, diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index 48665e8..3fdbdfe 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -52,7 +52,7 @@ class WebApplication : public WebView::EventListener { void Suspend(); void Terminate(); - void ClosePageFromOnTerminate(); + void ClosePage(); std::string data_path() const { return app_data_path_; } void set_terminator(std::function terminator) { terminator_ = terminator; diff --git a/runtime/browser/web_view_impl.cc b/runtime/browser/web_view_impl.cc index cc52275..162bca9 100644 --- a/runtime/browser/web_view_impl.cc +++ b/runtime/browser/web_view_impl.cc @@ -633,6 +633,7 @@ void WebViewImpl::InitWindowCreateCallback() { auto close_callback = [](void* user_data, Evas_Object*, void*) { + LOGGER(DEBUG) << "close_callback is called"; WebViewImpl* self = static_cast(user_data); if (!self->listener_) { return; -- 2.7.4