am 7c556549: Merge changes Icdefb5ff,Icd7f5f03

* commit '7c556549079dbcc3f6f7ef4376978cd8c598aa62':
  Fix potential race introduced in Icd7f5f03
  SocketClient: add optional reference counting
This commit is contained in:
Brad Fitzpatrick 2011-03-23 12:04:31 -07:00 committed by Android Git Automerger
commit cb1e616e3c
3 changed files with 41 additions and 3 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}
}
}