From 9e651b39e416171812d0dd3835a0cb9958aed264 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 10 Apr 2015 11:40:45 -0700 Subject: Add some TRACE around pinging (for now), and refactor service/One to just run in the foreground as some platforms may not require threads at all. --- service/One.cpp | 152 +++++++++++++++++++++++++++----------------------------- service/One.hpp | 26 ++++++---- 2 files changed, 89 insertions(+), 89 deletions(-) (limited to 'service') diff --git a/service/One.cpp b/service/One.cpp index 2ebfd285..20be7006 100644 --- a/service/One.cpp +++ b/service/One.cpp @@ -39,7 +39,6 @@ #include "../node/InetAddress.hpp" #include "../osdep/Phy.hpp" -#include "../osdep/Thread.hpp" #include "../osdep/OSUtils.hpp" #include "One.hpp" @@ -109,22 +108,73 @@ public: in6.sin6_port = in4.sin_port; _v6UdpSocket = _phy.udpBind((const struct sockaddr *)&in6,this,131072); _v6TcpListenSocket = _phy.tcpListen((const struct sockaddr *)&in6,this); - - _thread = Thread::start(this); } virtual ~OneImpl() { - if (reasonForTermination() == ONE_STILL_RUNNING) { - terminate(); - waitForTermination(); - } _phy.close(_v4UdpSocket); _phy.close(_v6UdpSocket); _phy.close(_v4TcpListenSocket); _phy.close(_v6TcpListenSocket); } + virtual ReasonForTermination run() + { + try { + _node = new Node( + OSUtils::now(), + this, + SnodeDataStoreGetFunction, + SnodeDataStorePutFunction, + SnodeWirePacketSendFunction, + SnodeVirtualNetworkFrameFunction, + SnodeVirtualNetworkConfigFunction, + SnodeEventCallback, + ((_overrideRootTopology.length() > 0) ? _overrideRootTopology.c_str() : (const char *)0)); + + if (_master) + _node->setNetconfMaster((void *)_master); + + _nextBackgroundTaskDeadline = 0; + for(;;) { + _run_m.lock(); + if (!_run) { + _run_m.unlock(); + _termReason_m.lock(); + _termReason = ONE_NORMAL_TERMINATION; + _termReason_m.unlock(); + break; + } else _run_m.unlock(); + + uint64_t dl = _nextBackgroundTaskDeadline; + uint64_t now = OSUtils::now(); + + if (dl <= now) { + _node->processBackgroundTasks(now,const_cast(&_nextBackgroundTaskDeadline)); + dl = _nextBackgroundTaskDeadline; + now = OSUtils::now(); + } + + const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; + printf("polling: %lums timeout\n",delay); + _phy.poll(delay); + } + } catch (std::exception &exc) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = exc.what(); + } catch ( ... ) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "unexpected exception in main thread"; + } + + delete _node; + _node = (Node *)0; + + return _termReason; + } + virtual ReasonForTermination reasonForTermination() const { Mutex::Lock _l(_termReason_m); @@ -137,12 +187,6 @@ public: return _fatalErrorMessage; } - virtual void waitForTermination() - { - if (reasonForTermination() == ONE_STILL_RUNNING) - Thread::join(_thread); - } - virtual void terminate() { _run_m.lock(); @@ -155,21 +199,23 @@ public: inline void phyOnDatagramFunction(PhySocket *sock,const struct sockaddr *from,void *data,unsigned long len) { - ZT1_ResultCode rc = _node->processWirePacket( - OSUtils::now(), - (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big - 0, - data, - len, - const_cast(&_nextBackgroundTaskDeadline)); - if (ZT1_ResultCode_isFatal(rc)) { - char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket(%d)",(int)rc); - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = tmp; - this->terminate(); - } + try { + ZT1_ResultCode rc = _node->processWirePacket( + OSUtils::now(), + (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big + 0, + data, + len, + const_cast(&_nextBackgroundTaskDeadline)); + if (ZT1_ResultCode_isFatal(rc)) { + char tmp[256]; + Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket(%d)",(int)rc); + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = tmp; + this->terminate(); + } + } catch ( ... ) {} } inline void phyOnTcpConnectFunction(PhySocket *sock,bool success) @@ -309,55 +355,6 @@ public: fflush(stderr); } - void threadMain() - throw() - { - _nextBackgroundTaskDeadline = 0; - try { - _node = new Node( - OSUtils::now(), - this, - SnodeDataStoreGetFunction, - SnodeDataStorePutFunction, - SnodeWirePacketSendFunction, - SnodeVirtualNetworkFrameFunction, - SnodeVirtualNetworkConfigFunction, - SnodeEventCallback, - ((_overrideRootTopology.length() > 0) ? _overrideRootTopology.c_str() : (const char *)0)); - - if (_master) - _node->setNetconfMaster((void *)_master); - - for(;;) { - _run_m.lock(); - if (!_run) { - _run_m.unlock(); - break; - } else _run_m.unlock(); - - uint64_t dl = _nextBackgroundTaskDeadline; - uint64_t now = OSUtils::now(); - - if (dl <= now) { - _node->processBackgroundTasks(now,const_cast(&_nextBackgroundTaskDeadline)); - dl = _nextBackgroundTaskDeadline; - now = OSUtils::now(); - } - - _phy.poll((dl > now) ? (unsigned long)(dl - now) : 100); - } - } catch (std::exception &exc) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = exc.what(); - } catch ( ... ) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "unexpected exception in main thread"; - } - delete _node; - } - private: const std::string _homePath; SimpleFunctionPhy _phy; @@ -368,7 +365,6 @@ private: PhySocket *_v6UdpSocket; PhySocket *_v4TcpListenSocket; PhySocket *_v6TcpListenSocket; - Thread _thread; volatile uint64_t _nextBackgroundTaskDeadline; ReasonForTermination _termReason; diff --git a/service/One.hpp b/service/One.hpp index 26071656..1a33dc72 100644 --- a/service/One.hpp +++ b/service/One.hpp @@ -75,7 +75,10 @@ public: static std::string platformDefaultHomePath(); /** - * Create and start a new instance of the service + * Create a new instance of the service + * + * Once created, you must call the run() method to actually start + * processing. * * @param hp Home path * @param port TCP and UDP port for packets and HTTP control @@ -88,10 +91,18 @@ public: NetworkConfigMaster *master = (NetworkConfigMaster *)0, const char *overrideRootTopology = (const char *)0); + virtual ~One(); + /** - * Deletion will block until service stops if it's still running + * Execute the service main I/O loop until terminated + * + * The terminate() method may be called from a signal handler or another + * thread to terminate execution. Otherwise this will not return unless + * another condition terminates execution such as a fatal error. + * + * @param */ - virtual ~One(); + virtual ReasonForTermination run() = 0; /** * @return Reason for terminating or ONE_STILL_RUNNING if running @@ -104,14 +115,7 @@ public: virtual std::string fatalErrorMessage() const = 0; /** - * Block until service terminates - */ - virtual void waitForTermination() = 0; - - /** - * Terminate background service - * - * Actual shutdown might take a few seconds. + * Terminate background service (can be called from other threads) */ virtual void terminate() = 0; -- cgit v1.2.3