diff options
-rw-r--r-- | include/sysutils/SocketListener.h | 3 | ||||
-rw-r--r-- | libsysutils/src/SocketListener.cpp | 76 |
2 files changed, 53 insertions, 26 deletions
diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h index 649c89a..c204a0f 100644 --- a/include/sysutils/SocketListener.h +++ b/include/sysutils/SocketListener.h @@ -44,10 +44,13 @@ public: void runOnEachSocket(SocketClientCommand *command); + bool release(SocketClient *c) { return release(c, true); } + protected: virtual bool onDataAvailable(SocketClient *c) = 0; private: + bool release(SocketClient *c, bool wakeup); static void *threadStart(void *obj); void runListener(); void init(const char *socketName, int socketFd, bool listen, bool useCmdNum); diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 1b53867..5c75206 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -29,6 +29,9 @@ #include <sysutils/SocketListener.h> #include <sysutils/SocketClient.h> +#define CtrlPipe_Shutdown 0 +#define CtrlPipe_Wakeup 1 + SocketListener::SocketListener(const char *socketName, bool listen) { init(socketName, -1, listen, false); } @@ -101,7 +104,7 @@ int SocketListener::startListener() { } int SocketListener::stopListener() { - char c = 0; + char c = CtrlPipe_Shutdown; int rc; rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1)); @@ -143,7 +146,7 @@ void *SocketListener::threadStart(void *obj) { void SocketListener::runListener() { - SocketClientCollection *pendingList = new SocketClientCollection(); + SocketClientCollection pendingList; while(1) { SocketClientCollection::iterator it; @@ -167,8 +170,9 @@ void SocketListener::runListener() { // NB: calling out to an other object with mClientsLock held (safe) int fd = (*it)->getSocket(); FD_SET(fd, &read_fds); - if (fd > max) + if (fd > max) { max = fd; + } } pthread_mutex_unlock(&mClientsLock); SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName); @@ -181,8 +185,14 @@ void SocketListener::runListener() { } else if (!rc) continue; - if (FD_ISSET(mCtrlPipe[0], &read_fds)) - break; + if (FD_ISSET(mCtrlPipe[0], &read_fds)) { + char c = CtrlPipe_Shutdown; + TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1)); + if (c == CtrlPipe_Shutdown) { + break; + } + continue; + } if (mListen && FD_ISSET(mSock, &read_fds)) { struct sockaddr addr; socklen_t alen; @@ -204,14 +214,14 @@ void SocketListener::runListener() { } /* Add all active clients to the pending list first */ - pendingList->clear(); + pendingList.clear(); pthread_mutex_lock(&mClientsLock); for (it = mClients->begin(); it != mClients->end(); ++it) { SocketClient* c = *it; // NB: calling out to an other object with mClientsLock held (safe) int fd = c->getSocket(); if (FD_ISSET(fd, &read_fds)) { - pendingList->push_back(c); + pendingList.push_back(c); c->incRef(); } } @@ -219,31 +229,45 @@ void SocketListener::runListener() { /* Process the pending list, since it is owned by the thread, * there is no need to lock it */ - while (!pendingList->empty()) { + while (!pendingList.empty()) { /* Pop the first item from the list */ - it = pendingList->begin(); + it = pendingList.begin(); SocketClient* c = *it; - pendingList->erase(it); - /* Process it, if false is returned and our sockets are - * connection-based, remove and destroy it */ - if (!onDataAvailable(c) && mListen) { - /* Remove the client from our array */ - SLOGV("going to zap %d for %s", c->getSocket(), mSocketName); - pthread_mutex_lock(&mClientsLock); - for (it = mClients->begin(); it != mClients->end(); ++it) { - if (*it == c) { - mClients->erase(it); - break; - } - } - pthread_mutex_unlock(&mClientsLock); - /* Remove our reference to the client */ - c->decRef(); + pendingList.erase(it); + /* Process it, if false is returned, remove from list */ + if (!onDataAvailable(c)) { + release(c, false); } c->decRef(); } } - delete pendingList; +} + +bool SocketListener::release(SocketClient* c, bool wakeup) { + bool ret = false; + /* if our sockets are connection-based, remove and destroy it */ + if (mListen && c) { + /* Remove the client from our array */ + SLOGV("going to zap %d for %s", c->getSocket(), mSocketName); + pthread_mutex_lock(&mClientsLock); + SocketClientCollection::iterator it; + for (it = mClients->begin(); it != mClients->end(); ++it) { + if (*it == c) { + mClients->erase(it); + ret = true; + break; + } + } + pthread_mutex_unlock(&mClientsLock); + if (ret) { + ret = c->decRef(); + if (wakeup) { + char b = CtrlPipe_Wakeup; + TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1)); + } + } + } + return ret; } void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) { |