This is an automated email from the ASF dual-hosted git repository.

luckychen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new af7c957  Feature/try fix top native crash fd problem (#2854)
af7c957 is described below

commit af7c957b21b476793cb904dd2e05245f5d31c31b
Author: darin <[email protected]>
AuthorDate: Wed Aug 28 16:33:13 2019 +0800

    Feature/try fix top native crash fd problem (#2854)
    
    * add pid and genId to ashmem
    
    * try fix fd problem
    
    所有的 fd 操作都控制在局部变量. 去掉所有的静态变量. 防止全局污染
    
    * Rename client name to file name and return base if fd create failed
    
    * make sure close fd happened in deconstructor.
---
 .../bridge/multi_process_and_so_initializer.cpp    |  10 +-
 .../bridge/multi_process_and_so_initializer.h      |   2 +-
 .../bridge/script_bridge_in_multi_process.cpp      |   9 +-
 .../bridge/script_bridge_in_multi_process.h        |   4 +-
 .../android/multiprocess/weex_js_connection.cpp    | 105 ++++++++++++---------
 .../android/multiprocess/weex_js_connection.h      |  43 ++++++++-
 6 files changed, 112 insertions(+), 61 deletions(-)

diff --git 
a/weex_core/Source/android/bridge/multi_process_and_so_initializer.cpp 
b/weex_core/Source/android/bridge/multi_process_and_so_initializer.cpp
index a16e31c..40ab7b3 100644
--- a/weex_core/Source/android/bridge/multi_process_and_so_initializer.cpp
+++ b/weex_core/Source/android/bridge/multi_process_and_so_initializer.cpp
@@ -32,17 +32,17 @@
 namespace WeexCore {
 
 bool MultiProcessAndSoInitializer::Init(const 
std::function<void(IPCHandler*)>& OnHandlerCreated,
-                                        const 
std::function<bool(std::unique_ptr<WeexJSConnection>, 
std::unique_ptr<IPCHandler>, std::unique_ptr<IPCHandler>)>& OnInitFinished,
+                                        const 
std::function<bool(std::unique_ptr<WeexJSConnection>)>& OnInitFinished,
                                         const std::function<void(const char*, 
const char*, const char*)>& ReportException){
   bool reinit = false;
   LOGE("MultiProcessAndSoInitializer IS IN init");
 startInitFrameWork:
   try {
-    auto handler = std::move(createIPCHandler());
     auto server_handler = std::move(createIPCHandler());
     OnHandlerCreated(server_handler.get());
-    std::unique_ptr<WeexJSConnection> connection(new WeexJSConnection());
-    auto sender = connection->start(handler.get(), server_handler.get(), 
reinit);
+    std::unique_ptr<WeexJSConnection> connection(new WeexJSConnection(new 
WeexConnInfo(std::move(createIPCHandler()), true),
+        new WeexConnInfo(std::move(server_handler), false)));
+    auto sender = connection->start(reinit);
     if (sender == nullptr) {
       LOGE("JSFramwork init start sender is null");
       if (!reinit) {
@@ -52,7 +52,7 @@ startInitFrameWork:
         return false;
       }
     } else {
-      OnInitFinished(std::move(connection), std::move(handler), 
std::move(server_handler));
+      OnInitFinished(std::move(connection));
     }
   } catch (IPCException& e) {
     LOGE("WeexProxy catch:%s", e.msg());
diff --git a/weex_core/Source/android/bridge/multi_process_and_so_initializer.h 
b/weex_core/Source/android/bridge/multi_process_and_so_initializer.h
index 424e4d7..e972204 100644
--- a/weex_core/Source/android/bridge/multi_process_and_so_initializer.h
+++ b/weex_core/Source/android/bridge/multi_process_and_so_initializer.h
@@ -32,7 +32,7 @@ class MultiProcessAndSoInitializer {
   virtual ~MultiProcessAndSoInitializer() {}
 
   bool Init(const std::function<void(IPCHandler*)>&,
-            const std::function<bool(std::unique_ptr<WeexJSConnection>, 
std::unique_ptr<IPCHandler>, std::unique_ptr<IPCHandler>)>&,
+            const std::function<bool(std::unique_ptr<WeexJSConnection>)>&,
             const std::function<void(const char*, const char*, const char*)>&);
 };
 }  // namespace WeexCore
diff --git a/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp 
b/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
index 96ca9f0..7cc4ec6 100644
--- a/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
+++ b/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
@@ -1004,16 +1004,11 @@ 
ScriptBridgeInMultiProcess::ScriptBridgeInMultiProcess() {
   LOGE("ScriptBridgeInMultiProcess");
   bool passable = initializer->Init(
       [this](IPCHandler *handler) { RegisterIPCCallback(handler); },
-      [this](std::unique_ptr<WeexJSConnection> connection,
-             std::unique_ptr<IPCHandler> handler,
-             std::unique_ptr<IPCHandler> server_handler) {
+      [this](std::unique_ptr<WeexJSConnection> connection) {
         static_cast<bridge::script::ScriptSideInMultiProcess *>(script_side())
             ->set_sender(connection->sender());
         connection_ = std::move(connection);
-        handler_ = std::move(handler);
-        server_handler_ = std::move(server_handler);
-        LOGE("ScriptBridgeInMultiProcess finish %p %p", server_handler_.get(),
-             server_handler.get());
+        LOGE("ScriptBridgeInMultiProcess finish");
         return true;
       },
       [this](const char *page_id, const char *func,
diff --git a/weex_core/Source/android/bridge/script_bridge_in_multi_process.h 
b/weex_core/Source/android/bridge/script_bridge_in_multi_process.h
index 7296342..3d85c3f 100644
--- a/weex_core/Source/android/bridge/script_bridge_in_multi_process.h
+++ b/weex_core/Source/android/bridge/script_bridge_in_multi_process.h
@@ -24,6 +24,7 @@
 
 class IPCHandler;
 class WeexJSConnection;
+class WeexConnInfo;
 class IPCHandler;
 namespace WeexCore {
 
@@ -31,13 +32,10 @@ class ScriptBridgeInMultiProcess : public ScriptBridge {
  public:
   ScriptBridgeInMultiProcess();
   ~ScriptBridgeInMultiProcess();
-
   void RegisterIPCCallback(IPCHandler *handler);
 
  private:
   std::unique_ptr<WeexJSConnection> connection_;
-  std::unique_ptr<IPCHandler> handler_;
-  std::unique_ptr<IPCHandler> server_handler_;
   DISALLOW_COPY_AND_ASSIGN(ScriptBridgeInMultiProcess);
 };
 }  // namespace WeexCore
diff --git a/weex_core/Source/android/multiprocess/weex_js_connection.cpp 
b/weex_core/Source/android/multiprocess/weex_js_connection.cpp
index 11bd292..e4aefa8 100644
--- a/weex_core/Source/android/multiprocess/weex_js_connection.cpp
+++ b/weex_core/Source/android/multiprocess/weex_js_connection.cpp
@@ -46,8 +46,6 @@
 static bool s_in_find_icu = false;
 static std::string g_crashFileName;
 
-volatile static bool fd_server_closed = false;
-
 static void doExec(int fdClient, int fdServer, bool traceEnable, bool 
startupPie);
 
 static int copyFile(const char *SourceFile, const char *NewFile);
@@ -56,13 +54,6 @@ static void closeAllButThis(int fd, int fd2);
 
 static void printLogOnFile(const char *log);
 
-static void closeServerFd(int fd) {
-    if(fd_server_closed)
-        return;
-    close(fd);
-    fd_server_closed = true;
-}
-
 static bool checkOrCreateCrashFile(const char* file) {
     if (file == nullptr) {
         LOGE("checkOrCreateCrashFile Pass error file name!");
@@ -121,8 +112,11 @@ struct WeexJSConnection::WeexJSConnectionImpl {
     pid_t child{0};
 };
 
-WeexJSConnection::WeexJSConnection()
+WeexJSConnection::WeexJSConnection(WeexConnInfo* client, WeexConnInfo *server)
         : m_impl(new WeexJSConnectionImpl) {
+  this->client_.reset(client);
+  this->server_.reset(server);
+
   if (SoUtils::crash_file_path() != nullptr) {
     if (checkDirOrFileIsLink(SoUtils::crash_file_path())) {
         std::string tmp = SoUtils::crash_file_path();
@@ -151,10 +145,6 @@ WeexJSConnection::~WeexJSConnection() {
   end();
 }
 
-struct ThreadData {
-    int ipcServerFd;
-    IPCHandler *ipcServerHandler;
-};
 // -1 unFinish, 0 error, 1 success
 enum NewThreadStatus {
     UNFINISH,
@@ -165,19 +155,18 @@ enum NewThreadStatus {
 static volatile int newThreadStatus = UNFINISH;
 
 static void *newIPCServer(void *_td) {
-    ThreadData *td = static_cast<ThreadData *>(_td);
-    void *base = mmap(nullptr, IPCFutexPageQueue::ipc_size, PROT_READ | 
PROT_WRITE, MAP_SHARED,
-                      td->ipcServerFd, 0);
+    WeexConnInfo  *server = static_cast<WeexConnInfo *>(_td);
+    void *base = server->mmap_for_ipc();
+
     if (base == MAP_FAILED) {
         LOGE("newIPCServer start map filed errno %d ", errno);
         int _errno = errno;
-        close(td->ipcServerFd);
         //throw IPCException("failed to map ashmem region: %s", 
strerror(_errno));
         newThreadStatus = ERROR;
         return nullptr;
     }
 
-    IPCHandler *handler = td->ipcServerHandler;
+    IPCHandler *handler = server->handler.get();
     std::unique_ptr<IPCFutexPageQueue> futexPageQueue(
             new IPCFutexPageQueue(base, IPCFutexPageQueue::ipc_size, 0));
     const std::unique_ptr<IPCHandler> &testHandler = createIPCHandler();
@@ -190,49 +179,42 @@ static void *newIPCServer(void *_td) {
       listener->listen();
     } catch (IPCException &e) {
         LOGE("IPCException server died %s",e.msg());
-        closeServerFd(td->ipcServerFd);
         base::android::DetachFromVM();
         pthread_exit(NULL);
     }
     return nullptr;
 }
 
+IPCSender *WeexJSConnection::start(bool reinit) {
+  if(client_== nullptr || client_.get() == nullptr) {
+    return nullptr;
+  }
 
-IPCSender *WeexJSConnection::start(IPCHandler *handler, IPCHandler 
*serverHandler, bool reinit) {
-  int fd = ashmem_create_region("WEEX_IPC_CLIENT", 
IPCFutexPageQueue::ipc_size);
-  if (-1 == fd) {
-    throw IPCException("failed to create ashmem region: %s", strerror(errno));
+  if(server_ == nullptr || server_.get() == nullptr) {
+    return nullptr;
   }
-  void *base = mmap(nullptr, IPCFutexPageQueue::ipc_size, PROT_READ | 
PROT_WRITE, MAP_SHARED,
-                    fd, 0);
+
+  void *base = client_->mmap_for_ipc();
   if (base == MAP_FAILED) {
     int _errno = errno;
-    close(fd);
     throw IPCException("failed to map ashmem region: %s", strerror(_errno));
   }
+
   std::unique_ptr<IPCFutexPageQueue> futexPageQueue(
           new IPCFutexPageQueue(base, IPCFutexPageQueue::ipc_size, 0));
-  std::unique_ptr<IPCSender> sender(createIPCSender(futexPageQueue.get(), 
handler));
+  std::unique_ptr<IPCSender> sender(createIPCSender(futexPageQueue.get(), 
client_->handler.get()));
   m_impl->serverSender = std::move(sender);
   m_impl->futexPageQueue = std::move(futexPageQueue);
 
-  int fd2 = ashmem_create_region("WEEX_IPC_SERVER", 
IPCFutexPageQueue::ipc_size);
-  if (-1 == fd2) {
-    throw IPCException("failed to create ashmem region: %s", strerror(errno));
-  }
-  fd_server_closed = false;
-  ThreadData td = { static_cast<int>(fd2), static_cast<IPCHandler 
*>(serverHandler) };
-
   pthread_attr_t threadAttr;
   newThreadStatus = UNFINISH;
 
   pthread_attr_init(&threadAttr);
   pthread_t ipcServerThread;
-  int i = pthread_create(&ipcServerThread, &threadAttr, newIPCServer, &td);
+  int i = pthread_create(&ipcServerThread, &threadAttr, newIPCServer, 
server_.get());
   if(i != 0) {
     throw IPCException("failed to create ipc server thread");
   }
-
   while (newThreadStatus == UNFINISH) {
     continue;
   }
@@ -282,23 +264,19 @@ IPCSender *WeexJSConnection::start(IPCHandler *handler, 
IPCHandler *serverHandle
   if (child == -1) {
     int myerrno = errno;
     munmap(base, IPCFutexPageQueue::ipc_size);
-    close(fd);
-    closeServerFd(fd2);
     throw IPCException("failed to fork: %s", strerror(myerrno));
   } else if (child == 0) {
     LOGE("weexcore fork child success\n");
     // the child
-    closeAllButThis(fd, fd2);
+    closeAllButThis(client_->ipcFd, server_->ipcFd);
     // implements close all but handles[1]
     // do exec
-    doExec(fd, fd2, true, startupPie);
+    doExec(client_->ipcFd, server_->ipcFd, true, startupPie);
     LOGE("exec Failed completely.");
     // failed to exec
     _exit(1);
   } else {
     printLogOnFile("fork success on main process and start 
m_impl->futexPageQueue->spinWaitPeer()");
-    close(fd);
-    closeServerFd(fd2);
     m_impl->child = child;
     try {
       m_impl->futexPageQueue->spinWaitPeer();
@@ -617,3 +595,44 @@ int copyFile(const char *SourceFile, const char *NewFile) {
     return 1;
   }
 }
+
+void *WeexConnInfo::mmap_for_ipc() {
+  pid_t pid = getpid();
+  std::string fileName(this->is_client ? "WEEX_IPC_CLIENT" : 
"WEEX_IPC_SERVER");
+  fileName += std::to_string(pid);
+  int fd = -1;
+  int initTimes = 1;
+  void *base = MAP_FAILED;
+  do {
+    fd = ashmem_create_region(fileName.c_str(), IPCFutexPageQueue::ipc_size);
+    if (-1 == fd) {
+      if (this->is_client) {
+        throw IPCException("failed to create ashmem region: %s", 
strerror(errno));
+      } else {
+        LOGE("failed to create ashmem region: %s", strerror(errno))
+        return base;
+      }
+    }
+    base = mmap(nullptr, IPCFutexPageQueue::ipc_size, PROT_READ | PROT_WRITE, 
MAP_SHARED,
+                fd, 0);
+    if (base == MAP_FAILED) {
+      close(fd);
+      fd = -1;
+      int _errno = errno;
+      initTimes++;
+      if (_errno == EBADF || _errno == EACCES) {
+        LOGE("start map filed errno %d should retry", errno);
+        continue;
+      } else {
+        if (this->is_client) {
+          throw IPCException("start map filed errno %d", errno);
+        } else {
+          LOGE("start map filed errno %d", errno)
+        }
+        break;
+      }
+    }
+  } while ((initTimes <= 2) && base == MAP_FAILED);
+  this->ipcFd = fd;
+  return base;
+}
diff --git a/weex_core/Source/android/multiprocess/weex_js_connection.h 
b/weex_core/Source/android/multiprocess/weex_js_connection.h
index 50e4adf..23a032f 100644
--- a/weex_core/Source/android/multiprocess/weex_js_connection.h
+++ b/weex_core/Source/android/multiprocess/weex_js_connection.h
@@ -20,22 +20,61 @@
 #define WEEXJSCONNECTION_H
 
 #include <memory>
+#include <unistd.h>
+#include <sys/mman.h>
 
 class IPCSender;
 class IPCHandler;
 
+
+class WeexConnInfo {
+ public:
+  std::unique_ptr<IPCHandler> handler;
+  int ipcFd;
+
+  WeexConnInfo(std::unique_ptr<IPCHandler> handler, bool isClient) {
+    this->handler = std::move(handler);
+    ipcFd = -1;
+    is_client = isClient;
+  }
+
+  ~WeexConnInfo() {
+    closeFd();
+  }
+
+  void *mmap_for_ipc();
+
+  void closeFd() {
+    if(ipcFd == -1) {
+      return;
+    }
+
+    if(hasBeenClosed)
+      return;
+    hasBeenClosed = true;
+    close(ipcFd);
+  }
+
+ private:
+  bool hasBeenClosed = false;
+  bool is_client = false;
+};
+
 class WeexJSConnection {
 public:
-    WeexJSConnection();
+    WeexJSConnection(WeexConnInfo* client, WeexConnInfo *server);
 
     ~WeexJSConnection();
 
-    IPCSender *start(IPCHandler *handler, IPCHandler *serverHandler, bool 
reinit);
+    IPCSender *start(bool reinit);
 
     void end();
 
     IPCSender* sender();
 
+  std::unique_ptr<WeexConnInfo> client_;
+  std::unique_ptr<WeexConnInfo> server_;
+
 private:
     struct WeexJSConnectionImpl;
 

Reply via email to