summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2011-03-23 11:57:49 -0700
committerAndroid Code Review <code-review@android.com>2011-03-23 11:57:49 -0700
commit7c556549079dbcc3f6f7ef4376978cd8c598aa62 (patch)
tree7667b9535a0f4d95d755f2e544182f04e9993879
parent499b45a3597bc2434bcc0974660470192ab4ff06 (diff)
parent3549b0dc2829184f9911d27a6ab0cf39b19764f1 (diff)
downloadsystem_core-7c556549079dbcc3f6f7ef4376978cd8c598aa62.zip
system_core-7c556549079dbcc3f6f7ef4376978cd8c598aa62.tar.gz
system_core-7c556549079dbcc3f6f7ef4376978cd8c598aa62.tar.bz2
Merge changes Icdefb5ff,Icd7f5f03
* changes: Fix potential race introduced in Icd7f5f03 SocketClient: add optional reference counting
-rw-r--r--include/sysutils/SocketClient.h11
-rw-r--r--libsysutils/src/SocketClient.cpp24
-rw-r--r--libsysutils/src/SocketListener.cpp9
3 files changed, 41 insertions, 3 deletions
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index 2fcc331..d6bb7d5 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -19,6 +19,10 @@ class SocketClient {
/* Peer group ID */
gid_t mGid;
+ /* Reference count (starts at 1) */
+ pthread_mutex_t mRefCountMutex;
+ int mRefCount;
+
public:
SocketClient(int sock);
virtual ~SocketClient() {}
@@ -34,6 +38,13 @@ public:
// Sending binary data:
int sendData(const void *data, int len);
+
+ // Optional reference counting. Reference count starts at 1. If
+ // it's decremented to 0, it deletes itself.
+ // SocketListener creates a SocketClient (at refcount 1) and calls
+ // decRef() when it's done with the client.
+ void incRef();
+ bool decRef(); // returns true at 0 (but note: SocketClient already deleted)
};
typedef android::List<SocketClient *> SocketClientCollection;
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index a6aed26..90ca52e 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -15,8 +15,10 @@ SocketClient::SocketClient(int socket)
, mPid(-1)
, mUid(-1)
, mGid(-1)
+ , mRefCount(1)
{
pthread_mutex_init(&mWriteMutex, NULL);
+ pthread_mutex_init(&mRefCountMutex, NULL);
struct ucred creds;
socklen_t szCreds = sizeof(creds);
@@ -100,3 +102,25 @@ int SocketClient::sendData(const void* data, int len) {
pthread_mutex_unlock(&mWriteMutex);
return 0;
}
+
+void SocketClient::incRef() {
+ pthread_mutex_lock(&mRefCountMutex);
+ mRefCount++;
+ pthread_mutex_unlock(&mRefCountMutex);
+}
+
+bool SocketClient::decRef() {
+ bool deleteSelf = false;
+ pthread_mutex_lock(&mRefCountMutex);
+ mRefCount--;
+ if (mRefCount == 0) {
+ deleteSelf = true;
+ } else if (mRefCount < 0) {
+ SLOGE("SocketClient refcount went negative!");
+ }
+ pthread_mutex_unlock(&mRefCountMutex);
+ if (deleteSelf) {
+ delete this;
+ }
+ return deleteSelf;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 611d5fe..69ed79e 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -55,7 +55,7 @@ SocketListener::~SocketListener() {
}
SocketClientCollection::iterator it;
for (it = mClients->begin(); it != mClients->end();) {
- delete (*it);
+ (*it)->decRef();
it = mClients->erase(it);
}
delete mClients;
@@ -225,8 +225,11 @@ void SocketListener::runListener() {
}
pthread_mutex_unlock(&mClientsLock);
/* Destroy the client */
- close(c->getSocket());
- delete c;
+ int socket = c->getSocket();
+ if (c->decRef()) {
+ // Note: 'c' is deleted memory at this point.
+ close(socket);
+ }
}
}
}