summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sysutils/SocketListener.h3
-rw-r--r--libsysutils/src/SocketListener.cpp76
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) {