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

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new ea85a7d  use schedule_spawn to start accept threads when set to 0
ea85a7d is described below

commit ea85a7d59a3cbfa666091594e01db4ba20ea79f8
Author: Fei Deng <duke8...@gmail.com>
AuthorDate: Tue Nov 14 15:51:25 2017 -0600

    use schedule_spawn to start accept threads when set to 0
---
 iocore/net/P_NetAccept.h          |  4 ++++
 iocore/net/SSLSNIConfig.cc        |  2 +-
 iocore/net/UnixNetAccept.cc       |  4 ++++
 iocore/net/UnixNetProcessor.cc    |  8 ++++++--
 proxy/InkAPI.cc                   |  8 +++++---
 proxy/Main.cc                     | 32 ++++++++++++++++++++++----------
 proxy/http/HttpProxyServerMain.cc | 39 ++++++++++++++++++++++++++++++++++++++-
 proxy/http/HttpProxyServerMain.h  | 17 +++++++++++++++--
 8 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/iocore/net/P_NetAccept.h b/iocore/net/P_NetAccept.h
index a9c98ca..d14c5a5 100644
--- a/iocore/net/P_NetAccept.h
+++ b/iocore/net/P_NetAccept.h
@@ -39,6 +39,7 @@
 #ifndef __P_NETACCEPT_H__
 #define __P_NETACCEPT_H__
 
+#include <vector>
 #include "ts/ink_platform.h"
 #include "P_Connection.h"
 
@@ -114,4 +115,7 @@ struct NetAccept : public Continuation {
   virtual ~NetAccept() { action_ = nullptr; }
 };
 
+extern Ptr<ProxyMutex> naVecMutex;
+extern std::vector<NetAccept *> naVec;
+
 #endif
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
index fa51bf9..8f14d5b 100644
--- a/iocore/net/SSLSNIConfig.cc
+++ b/iocore/net/SSLSNIConfig.cc
@@ -42,7 +42,6 @@
 
 static ConfigUpdateHandler<SNIConfig> *sniConfigUpdate;
 struct NetAccept;
-extern std::vector<NetAccept *> naVec;
 Map<int, SSLNextProtocolSet *> snpsMap;
 extern TunnelHashMap TunnelMap;
 NextHopProperty::NextHopProperty()
@@ -226,6 +225,7 @@ SNIConfig::startup()
 void
 SNIConfig::cloneProtoSet()
 {
+  SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
   for (auto na : naVec) {
     if (na->snpa) {
       auto snps = na->snpa->cloneProtoSet();
diff --git a/iocore/net/UnixNetAccept.cc b/iocore/net/UnixNetAccept.cc
index aac3bbd..29775f1 100644
--- a/iocore/net/UnixNetAccept.cc
+++ b/iocore/net/UnixNetAccept.cc
@@ -31,6 +31,9 @@
 using NetAcceptHandler = int (NetAccept::*)(int, void *);
 int accept_till_done   = 1;
 
+// we need to protect naVec since it might be accessed
+// in different threads at the same time
+Ptr<ProxyMutex> naVecMutex;
 std::vector<NetAccept *> naVec;
 static void
 safe_delay(int msec)
@@ -139,6 +142,7 @@ Ldone:
 NetAccept *
 getNetAccept(int ID)
 {
+  SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
   return naVec.at(ID);
 }
 
diff --git a/iocore/net/UnixNetProcessor.cc b/iocore/net/UnixNetProcessor.cc
index 13d37a9..f63eaa0 100644
--- a/iocore/net/UnixNetProcessor.cc
+++ b/iocore/net/UnixNetProcessor.cc
@@ -30,7 +30,6 @@
 #include "StatPages.h"
 
 int net_accept_number = 0;
-extern std::vector<NetAccept *> naVec;
 NetProcessor::AcceptOptions const NetProcessor::DEFAULT_ACCEPT_OPTIONS;
 
 NetProcessor::AcceptOptions &
@@ -174,7 +173,12 @@ UnixNetProcessor::accept_internal(Continuation *cont, int 
fd, AcceptOptions cons
   } else {
     na->init_accept(nullptr);
   }
-  naVec.push_back(na);
+
+  {
+    SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
+    naVec.push_back(na);
+  }
+
 #ifdef TCP_DEFER_ACCEPT
   // set tcp defer accept timeout if it is configured, this will not trigger 
an accept until there is
   // data on the socket ready to be read
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index a077b21..eb59342 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -9289,12 +9289,13 @@ TSAcceptorGet(TSVConn sslp)
   return ssl_vc ? reinterpret_cast<TSAcceptor>(ssl_vc->accept_object) : 
nullptr;
 }
 
-extern std::vector<NetAccept *> naVec;
 TSAcceptor
 TSAcceptorGetbyID(int ID)
 {
-  Debug("ssl", "getNetAccept in INK API.cc %p", naVec.at(ID));
-  return reinterpret_cast<TSAcceptor>(naVec.at(ID));
+  SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
+  auto ret = naVec.at(ID);
+  Debug("ssl", "getNetAccept in INK API.cc %p", ret);
+  return reinterpret_cast<TSAcceptor>(ret);
 }
 
 int
@@ -9307,6 +9308,7 @@ TSAcceptorIDGet(TSAcceptor acceptor)
 int
 TSAcceptorCount()
 {
+  SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
   return naVec.size();
 }
 
diff --git a/proxy/Main.cc b/proxy/Main.cc
index 5117954..53a122a 100644
--- a/proxy/Main.cc
+++ b/proxy/Main.cc
@@ -128,9 +128,11 @@ static void *mgmt_lifecycle_msg_callback(void *x, char 
*data, int len);
 static void init_ssl_ctx_callback(void *ctx, bool server);
 static void load_ssl_file_callback(const char *ssl_file, unsigned int options);
 
-static int num_of_net_threads = ink_number_of_processors();
+// We need these two to be accessible somewhere else now
+int num_of_net_threads = ink_number_of_processors();
+int num_accept_threads = 0;
+
 static int num_of_udp_threads = 0;
-static int num_accept_threads = 0;
 static int num_task_threads   = 0;
 
 static char *http_accept_port_descriptor;
@@ -1718,7 +1720,7 @@ main(int /* argc ATS_UNUSED */, const char **argv)
   // We need to do this early so we can initialize the Machine
   // singleton, which depends on configuration values loaded in this.
   // We want to initialize Machine as early as possible because it
-  // has other dependencies. Hopefully not in init_HttpProxyServer().
+  // has other dependencies. Hopefully not in prep_HttpProxyServer().
   HttpConfig::startup();
   /* Set up the machine with the outbound address if that's set,
      or the inbound address if set, otherwise let it default.
@@ -1793,9 +1795,21 @@ main(int /* argc ATS_UNUSED */, const char **argv)
   ink_dns_init(makeModuleVersion(HOSTDB_MODULE_MAJOR_VERSION, 
HOSTDB_MODULE_MINOR_VERSION, PRIVATE_MODULE_HEADER));
   ink_split_dns_init(makeModuleVersion(1, 0, PRIVATE_MODULE_HEADER));
 
+  naVecMutex             = new_ProxyMutex();
+  started_et_net_threads = 0;
+
   // Do the inits for NetProcessors that use ET_NET threads. MUST be before 
starting those threads.
   netProcessor.init();
-  init_HttpProxyServer();
+  prep_HttpProxyServer();
+
+  if (num_accept_threads == 0) {
+    eventProcessor.schedule_spawn(&init_HttpProxyServer, ET_NET);
+  } else {
+    std::unique_lock<std::mutex> lock(proxyServerMutex);
+    et_net_threads_ready = true;
+    lock.unlock();
+    proxyServerCheck.notify_one();
+  }
 
   // !! ET_NET threads start here !!
   // This means any spawn scheduling must be done before this point.
@@ -1934,6 +1948,10 @@ main(int /* argc ATS_UNUSED */, const char **argv)
       if (delay_p && ink_atomic_cas(&delay_listen_for_cache_p, 0, 1)) {
         Debug("http_listen", "Delaying listen, waiting for cache 
initialization");
       } else {
+        // Use a condition variable to check if we are ready to call
+        // start_HttpProxyServer() when num_accept_threads is set to 0.
+        std::unique_lock<std::mutex> lock(proxyServerMutex);
+        proxyServerCheck.wait(lock, [] { return et_net_threads_ready; });
         start_HttpProxyServer(); // PORTS_READY_HOOK called from in here
       }
     }
@@ -1946,12 +1964,6 @@ main(int /* argc ATS_UNUSED */, const char **argv)
     // "Task" processor, possibly with its own set of task threads
     tasksProcessor.start(num_task_threads, stacksize);
 
-    int back_door_port = NO_FD;
-    REC_ReadConfigInteger(back_door_port, 
"proxy.config.process_manager.mgmt_port");
-    if (back_door_port != NO_FD) {
-      start_HttpProxyServerBackDoor(back_door_port, num_accept_threads > 0 ? 1 
: 0); // One accept thread is enough
-    }
-
     if (netProcessor.socks_conf_stuff->accept_enabled) {
       start_SocksProxy(netProcessor.socks_conf_stuff->accept_port);
     }
diff --git a/proxy/http/HttpProxyServerMain.cc 
b/proxy/http/HttpProxyServerMain.cc
index 21142ca..e4dce2d 100644
--- a/proxy/http/HttpProxyServerMain.cc
+++ b/proxy/http/HttpProxyServerMain.cc
@@ -39,6 +39,7 @@
 #include "ProtocolProbeSessionAccept.h"
 #include "http2/Http2SessionAccept.h"
 #include "HttpConnectionCount.h"
+#include "HttpProxyServerMain.h"
 
 #include <vector>
 
@@ -48,6 +49,15 @@ HttpSessionAccept *plugin_http_transparent_accept = nullptr;
 static SLL<SSLNextProtocolAccept> ssl_plugin_acceptors;
 static Ptr<ProxyMutex> ssl_plugin_mutex;
 
+// used to keep count of how many et_net threads we have started
+std::atomic<int> started_et_net_threads;
+std::mutex proxyServerMutex;
+std::condition_variable proxyServerCheck;
+bool et_net_threads_ready = false;
+
+extern int num_of_net_threads;
+extern int num_accept_threads;
+
 bool
 ssl_register_protocol(const char *protocol, Continuation *contp)
 {
@@ -227,7 +237,7 @@ MakeHttpProxyAcceptor(HttpProxyAcceptor &acceptor, 
HttpProxyPort &port, unsigned
 
 /// Do all pre-thread initialization / setup.
 void
-init_HttpProxyServer()
+prep_HttpProxyServer()
 {
   httpSessionManager.init();
 }
@@ -274,6 +284,25 @@ init_accept_HttpProxyServer(int n_accept_threads)
   }
 }
 
+/** Increment the counter to keep track of how many et_net threads
+ *  we have started. This function is scheduled at the start of each
+ *  et_net thread using schedule_spawn(). We also check immediately
+ *  after incrementing the counter to see whether all of the et_net
+ *  threads have started such that we can notify main() to call
+ *  start_HttpProxyServer().
+ */
+void
+init_HttpProxyServer(EThread *)
+{
+  auto check_et_net_num = ++started_et_net_threads;
+  if (check_et_net_num == num_of_net_threads) {
+    std::unique_lock<std::mutex> lock(proxyServerMutex);
+    et_net_threads_ready = true;
+    lock.unlock();
+    proxyServerCheck.notify_one();
+  }
+}
+
 void
 start_HttpProxyServer()
 {
@@ -318,6 +347,14 @@ start_HttpProxyServer()
     hook->invoke(TS_EVENT_LIFECYCLE_PORTS_READY, nullptr);
     hook = hook->next();
   }
+
+  // Start the back door, since it's just a special HttpProxyServer,
+  // the requirements to start it has been met if we got here.
+  int back_door_port = NO_FD;
+  REC_ReadConfigInteger(back_door_port, 
"proxy.config.process_manager.mgmt_port");
+  if (back_door_port != NO_FD) {
+    start_HttpProxyServerBackDoor(back_door_port, !!num_accept_threads); // 
One accept thread is enough
+  }
 }
 
 void
diff --git a/proxy/http/HttpProxyServerMain.h b/proxy/http/HttpProxyServerMain.h
index c640069..039c334 100644
--- a/proxy/http/HttpProxyServerMain.h
+++ b/proxy/http/HttpProxyServerMain.h
@@ -21,17 +21,25 @@
   limitations under the License.
  */
 
+#include <atomic>
+#include <mutex>
+#include <condition_variable>
+
 struct HttpProxyPort;
 
 /// Perform any pre-thread start initialization.
-void init_HttpProxyServer();
+void prep_HttpProxyServer();
 
 /** Initialize all HTTP proxy port data structures needed to accept 
connections.
  */
 void init_accept_HttpProxyServer(int n_accept_threads = 0);
 
+/** Checkes whether we can call start_HttpProxyServer().
+ */
+void init_HttpProxyServer(EThread *);
+
 /** Start the proxy server.
-    The port data should have been created by @c init_HttpProxyServer().
+    The port data should have been created by @c prep_HttpProxyServer().
 */
 void start_HttpProxyServer();
 
@@ -40,3 +48,8 @@ void stop_HttpProxyServer();
 void start_HttpProxyServerBackDoor(int port, int accept_threads = 0);
 
 NetProcessor::AcceptOptions make_net_accept_options(const HttpProxyPort *port, 
unsigned nthreads);
+
+extern std::atomic<int> started_et_net_threads;
+extern std::mutex proxyServerMutex;
+extern std::condition_variable proxyServerCheck;
+extern bool et_net_threads_ready;

-- 
To stop receiving notification emails like this one, please contact
a...@apache.org.

Reply via email to