Skip to content

Commit

Permalink
Fix a racing condition in ZygoteService
Browse files Browse the repository at this point in the history
The low-level logic for the ZygoteService uses one server process and
multiple client threads in the Zygote process(es). Data is transferred
between these threads using shared memory, a mutex and a condition
variable. Whenever one of the threads wants to start an operation, it
has to wait until the shared memory is in the correct state.

With pthread_cond_signal(), it was possible that not the correct thread
woke up. For example, client A might have woken up client B, leaving
the server thread sleeping and the operation would never be finished.
Similarly, the server might not have woken up the client whose request
it was currently serving, but a different client which was waiting to
start a new request.

Using pthread_cond_broadcast() fixes it, the checks whether the threads
should really do something are already in place.

Fixes rovo89#152.
  • Loading branch information
rovo89 committed May 8, 2016
1 parent 2071cfb commit cc0d213
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions xposed_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ static inline bool isServiceAccessible() {
void* looper(void* unused __attribute__((unused))) {
pthread_mutex_lock(&shared->workerMutex);
shared->state = STATE_IDLE;
pthread_cond_signal(&shared->workerCond);
pthread_cond_broadcast(&shared->workerCond);
while (1) {
while (shared->state != STATE_SERVICE_ACTION) {
pthread_cond_wait(&shared->workerCond, &shared->workerMutex);
Expand Down Expand Up @@ -217,7 +217,7 @@ void* looper(void* unused __attribute__((unused))) {
}

shared->state = STATE_SERVER_RESPONSE;
pthread_cond_signal(&shared->workerCond);
pthread_cond_broadcast(&shared->workerCond);
}

pthread_mutex_unlock(&shared->workerMutex);
Expand Down Expand Up @@ -252,7 +252,7 @@ static inline void callService(Action action) {
shared->action = action;
shared->state = STATE_SERVICE_ACTION;
shared->error = 0;
pthread_cond_signal(&shared->workerCond);
pthread_cond_broadcast(&shared->workerCond);

while (shared->state != STATE_SERVER_RESPONSE) {
pthread_cond_wait(&shared->workerCond, &shared->workerMutex);
Expand All @@ -262,7 +262,7 @@ static inline void callService(Action action) {
static inline void makeIdle() {
shared->action = OP_NONE;
shared->state = STATE_IDLE;
pthread_cond_signal(&shared->workerCond);
pthread_cond_broadcast(&shared->workerCond);
pthread_mutex_unlock(&shared->workerMutex);
}

Expand Down

0 comments on commit cc0d213

Please sign in to comment.