Merge changes Icdefb5ff,Icd7f5f03
* changes: Fix potential race introduced in Icd7f5f03 SocketClient: add optional reference counting
This commit is contained in:
commit
7c55654907
3 changed files with 41 additions and 3 deletions
|
|
@ -19,6 +19,10 @@ class SocketClient {
|
||||||
/* Peer group ID */
|
/* Peer group ID */
|
||||||
gid_t mGid;
|
gid_t mGid;
|
||||||
|
|
||||||
|
/* Reference count (starts at 1) */
|
||||||
|
pthread_mutex_t mRefCountMutex;
|
||||||
|
int mRefCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SocketClient(int sock);
|
SocketClient(int sock);
|
||||||
virtual ~SocketClient() {}
|
virtual ~SocketClient() {}
|
||||||
|
|
@ -34,6 +38,13 @@ public:
|
||||||
|
|
||||||
// Sending binary data:
|
// Sending binary data:
|
||||||
int sendData(const void *data, int len);
|
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;
|
typedef android::List<SocketClient *> SocketClientCollection;
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@ SocketClient::SocketClient(int socket)
|
||||||
, mPid(-1)
|
, mPid(-1)
|
||||||
, mUid(-1)
|
, mUid(-1)
|
||||||
, mGid(-1)
|
, mGid(-1)
|
||||||
|
, mRefCount(1)
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&mWriteMutex, NULL);
|
pthread_mutex_init(&mWriteMutex, NULL);
|
||||||
|
pthread_mutex_init(&mRefCountMutex, NULL);
|
||||||
|
|
||||||
struct ucred creds;
|
struct ucred creds;
|
||||||
socklen_t szCreds = sizeof(creds);
|
socklen_t szCreds = sizeof(creds);
|
||||||
|
|
@ -100,3 +102,25 @@ int SocketClient::sendData(const void* data, int len) {
|
||||||
pthread_mutex_unlock(&mWriteMutex);
|
pthread_mutex_unlock(&mWriteMutex);
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ SocketListener::~SocketListener() {
|
||||||
}
|
}
|
||||||
SocketClientCollection::iterator it;
|
SocketClientCollection::iterator it;
|
||||||
for (it = mClients->begin(); it != mClients->end();) {
|
for (it = mClients->begin(); it != mClients->end();) {
|
||||||
delete (*it);
|
(*it)->decRef();
|
||||||
it = mClients->erase(it);
|
it = mClients->erase(it);
|
||||||
}
|
}
|
||||||
delete mClients;
|
delete mClients;
|
||||||
|
|
@ -225,8 +225,11 @@ void SocketListener::runListener() {
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mClientsLock);
|
pthread_mutex_unlock(&mClientsLock);
|
||||||
/* Destroy the client */
|
/* Destroy the client */
|
||||||
close(c->getSocket());
|
int socket = c->getSocket();
|
||||||
delete c;
|
if (c->decRef()) {
|
||||||
|
// Note: 'c' is deleted memory at this point.
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue