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)
|
static void * decoder_task(mpd_unused void *arg)
|
||||||
{
|
{
|
||||||
notify_enter(&dc.notify);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
assert(dc.state == DECODE_STATE_STOP);
|
assert(dc.state == DECODE_STATE_STOP);
|
||||||
|
|
||||||
|
@ -115,8 +115,6 @@ void wait_main_task(void)
|
|||||||
{
|
{
|
||||||
assert(pthread_equal(main_task, pthread_self()));
|
assert(pthread_equal(main_task, pthread_self()));
|
||||||
|
|
||||||
notify_enter(&main_notify);
|
|
||||||
notify_wait(&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);
|
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)
|
void notify_wait(struct notify *notify)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(¬ify->mutex);
|
||||||
if (!notify->pending)
|
if (!notify->pending)
|
||||||
pthread_cond_wait(¬ify->cond, ¬ify->mutex);
|
pthread_cond_wait(¬ify->cond, ¬ify->mutex);
|
||||||
|
assert(notify->pending);
|
||||||
notify->pending = 0;
|
notify->pending = 0;
|
||||||
|
pthread_mutex_unlock(¬ify->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_signal(struct notify *notify)
|
void notify_signal(struct notify *notify)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(¬ify->mutex);
|
||||||
notify->pending = 1;
|
notify->pending = 1;
|
||||||
pthread_cond_signal(¬ify->cond);
|
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);
|
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);
|
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
|
* Wait for a notification. Return immediately if we have already
|
||||||
* been notified since we last returned from notify_wait().
|
* 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);
|
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
|
#endif
|
||||||
|
@ -67,8 +67,6 @@ static void *audio_output_task(void *arg)
|
|||||||
{
|
{
|
||||||
struct audio_output *ao = arg;
|
struct audio_output *ao = arg;
|
||||||
|
|
||||||
notify_enter(&ao->notify);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (ao->command) {
|
switch (ao->command) {
|
||||||
case AO_COMMAND_NONE:
|
case AO_COMMAND_NONE:
|
||||||
|
@ -384,8 +384,6 @@ static void do_play(void)
|
|||||||
|
|
||||||
static void * player_task(mpd_unused void *arg)
|
static void * player_task(mpd_unused void *arg)
|
||||||
{
|
{
|
||||||
notify_enter(&pc.notify);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (pc.command) {
|
switch (pc.command) {
|
||||||
case PLAYER_COMMAND_PLAY:
|
case PLAYER_COMMAND_PLAY:
|
||||||
|
Loading…
Reference in New Issue
Block a user