summaryrefslogtreecommitdiffstats
path: root/libsysutils
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2014-01-08 12:44:23 -0800
committerMark Salyzyn <salyzyn@google.com>2014-01-27 15:22:49 -0800
commit44b99c22af84331068935a9bc3e807165a88237c (patch)
tree6f2641e55435a0b47946d323b966543ae08e9061 /libsysutils
parent23f04107dcedcef22556c1f57502cdddbfa2663f (diff)
downloadsystem_core-44b99c22af84331068935a9bc3e807165a88237c.tar.gz
system_core-44b99c22af84331068935a9bc3e807165a88237c.tar.bz2
system_core-44b99c22af84331068935a9bc3e807165a88237c.zip
libsysutils: SocketListener export release
* Foreground thread (legacy) closes connection by reporting false return value for onDataAvailable. * Background thread can choose instead to close the connection asynchronously by calling release, must return true for the onDataAvailable method. (cherry picked from commit d7ad4e409eaac53db3a9789060097b712850b337) Change-Id: I70ab37d5c22b02804aa3b4dfb26cc9b75291f8b6
Diffstat (limited to 'libsysutils')
-rw-r--r--libsysutils/src/SocketListener.cpp76
1 files changed, 50 insertions, 26 deletions
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 1b53867c3..5c752066c 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) {