notify: protect notify->pending with the mutex
There was a known deadlocking bug in the notify library: when the other thread set notify->pending after the according check in notify_wait(), the latter thread was deadlocked. Resolve this by synchronizing all accesses to notify->pending with the notify object's mutex. Since notify_signal_sync() was never used, we can remove it. As a consequence, we don't need notify_enter() and notify_leave() anymore; eliminate them, too.
This commit is contained in:
parent
323e86489f
commit
58554e14f9
@ -167,8 +167,6 @@ stop_no_close:
|
||||
|
||||
static void * decoder_task(mpd_unused void *arg)
|
||||
{
|
||||
notify_enter(&dc.notify);
|
||||
|
||||
while (1) {
|
||||
assert(dc.state == DECODE_STATE_STOP);
|
||||
|
||||
|
@ -115,8 +115,6 @@ void wait_main_task(void)
|
||||
{
|
||||
assert(pthread_equal(main_task, pthread_self()));
|
||||
|
||||
notify_enter(&main_notify);
|
||||
notify_wait(&main_notify);
|
||||
notify_leave(&main_notify);
|
||||
}
|
||||
|
||||
|
20
src/notify.c
20
src/notify.c
@ -40,32 +40,20 @@ void notify_deinit(struct notify *notify)
|
||||
pthread_cond_destroy(¬ify->cond);
|
||||
}
|
||||
|
||||
void notify_enter(struct notify *notify)
|
||||
{
|
||||
pthread_mutex_lock(¬ify->mutex);
|
||||
}
|
||||
|
||||
void notify_leave(struct notify *notify)
|
||||
{
|
||||
pthread_mutex_unlock(¬ify->mutex);
|
||||
}
|
||||
|
||||
void notify_wait(struct notify *notify)
|
||||
{
|
||||
pthread_mutex_lock(¬ify->mutex);
|
||||
if (!notify->pending)
|
||||
pthread_cond_wait(¬ify->cond, ¬ify->mutex);
|
||||
assert(notify->pending);
|
||||
notify->pending = 0;
|
||||
pthread_mutex_unlock(¬ify->mutex);
|
||||
}
|
||||
|
||||
void notify_signal(struct notify *notify)
|
||||
{
|
||||
pthread_mutex_lock(¬ify->mutex);
|
||||
notify->pending = 1;
|
||||
pthread_cond_signal(¬ify->cond);
|
||||
}
|
||||
|
||||
void notify_signal_sync(struct notify *notify)
|
||||
{
|
||||
pthread_mutex_lock(¬ify->mutex);
|
||||
notify_signal(notify);
|
||||
pthread_mutex_unlock(¬ify->mutex);
|
||||
}
|
||||
|
17
src/notify.h
17
src/notify.h
@ -36,17 +36,6 @@ void notify_init(struct notify *notify);
|
||||
|
||||
void notify_deinit(struct notify *notify);
|
||||
|
||||
/**
|
||||
* The thread which shall be notified by this object must call this
|
||||
* function before any notify_wait() invocation. It locks the mutex.
|
||||
*/
|
||||
void notify_enter(struct notify *notify);
|
||||
|
||||
/**
|
||||
* Neutralize notify_leave().
|
||||
*/
|
||||
void notify_leave(struct notify *notify);
|
||||
|
||||
/**
|
||||
* Wait for a notification. Return immediately if we have already
|
||||
* been notified since we last returned from notify_wait().
|
||||
@ -58,10 +47,4 @@ void notify_wait(struct notify *notify);
|
||||
*/
|
||||
void notify_signal(struct notify *notify);
|
||||
|
||||
/**
|
||||
* Notify the thread synchonously, i.e. wait until it has received the
|
||||
* notification.
|
||||
*/
|
||||
void notify_signal_sync(struct notify *notify);
|
||||
|
||||
#endif
|
||||
|
@ -67,8 +67,6 @@ static void *audio_output_task(void *arg)
|
||||
{
|
||||
struct audio_output *ao = arg;
|
||||
|
||||
notify_enter(&ao->notify);
|
||||
|
||||
while (1) {
|
||||
switch (ao->command) {
|
||||
case AO_COMMAND_NONE:
|
||||
|
@ -384,8 +384,6 @@ static void do_play(void)
|
||||
|
||||
static void * player_task(mpd_unused void *arg)
|
||||
{
|
||||
notify_enter(&pc.notify);
|
||||
|
||||
while (1) {
|
||||
switch (pc.command) {
|
||||
case PLAYER_COMMAND_PLAY:
|
||||
|
Loading…
Reference in New Issue
Block a user