Locate ewk_view_page_close in extended main loop 88/110188/1
authorYoungsoo Choi <kenshin.choi@samsung.com>
Thu, 12 Jan 2017 05:52:13 +0000 (14:52 +0900)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Fri, 13 Jan 2017 07:29:28 +0000 (16:29 +0900)
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 <kenshin.choi@samsung.com>
12 files changed:
runtime/browser/ime_runtime.cc
runtime/browser/ime_runtime.h
runtime/browser/runtime.cc
runtime/browser/runtime.h
runtime/browser/runtime_process.cc
runtime/browser/ui_runtime.cc
runtime/browser/ui_runtime.h
runtime/browser/watch_runtime.cc
runtime/browser/watch_runtime.h
runtime/browser/web_application.cc
runtime/browser/web_application.h
runtime/browser/web_view_impl.cc

index 0527c83..78a890a 100644 (file)
@@ -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) {
index 1284a3d..b020539 100644 (file)
@@ -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_;
index 4298837..5861b08 100644 (file)
@@ -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> 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<Timer*>(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
index 00dea07..63ddc97 100755 (executable)
@@ -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
index 83d7645..757fdfa 100755 (executable)
@@ -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 =
         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";
index 4e20943..41fa8d9 100755 (executable)
@@ -142,7 +142,11 @@ bool UiRuntime::OnCreate() {
 }
 
 void UiRuntime::OnTerminate() {
-  ClosePageFromOnTerminate(application_.get());
+}
+
+void UiRuntime::Terminate() {
+  LOGGER(DEBUG);
+  ProcessClosingPage(application_.get());
 }
 
 void UiRuntime::OnPause() {
index 7aff1f7..1625abd 100644 (file)
@@ -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);
index 657a7f1..f166e72 100644 (file)
@@ -99,7 +99,10 @@ bool WatchRuntime::OnCreate() {
 }
 
 void WatchRuntime::OnTerminate() {
-  ClosePageFromOnTerminate(application_);
+}
+
+void WatchRuntime::Terminate() {
+  ProcessClosingPage(application_);
 }
 
 void WatchRuntime::OnPause() {
index 94c23d2..7fd5c3a 100644 (file)
@@ -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_;
index e0ef6a5..e11d9e0 100755 (executable)
@@ -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,
index 48665e8..3fdbdfe 100755 (executable)
@@ -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<void(void)> terminator) {
     terminator_ = terminator;
index cc52275..162bca9 100644 (file)
@@ -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<WebViewImpl*>(user_data);
     if (!self->listener_) {
       return;