From ad341e95d785e7d38dc9de052fb18a3c35c74977 Mon Sep 17 00:00:00 2001 From: Daniel MacDougall Date: Fri, 22 Jan 2016 16:59:28 -0800 Subject: [PATCH] Fix race condition allowing duplicate unbuffered reads Previously, this sequence of events would result in the same value being read twice from an unbuffered channel: Thread S Thread R -------- -------- unbuffered_chan_send() chan->data = data chan->w_waiting++ cond_wait on chan->m_mu unbuffered_chan_recv() mutex_lock chan->m_mu chan->w_waiting > 0 *data = chan->data cond_signal chan->w_cond mutex_unlock chan->m_mu unbuffered_chan_recv() mutex_lock chan->m_mu chan->w_waiting > 0 *data = chan->data cond_signal chan->w_cond mutex_unlock chan->m_mu chan->w_waiting-- mutex_unlock chan->m_mu Moving the chan->w_waiting-- to immediately after the data is read in unbuffered_chan_recv() prevents this double read. Fixes #23 --- src/chan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chan.c b/src/chan.c index d6989e8..4129f97 100644 --- a/src/chan.c +++ b/src/chan.c @@ -321,7 +321,6 @@ static int unbuffered_chan_send(chan_t* chan, void* data) // Block until reader consumed chan->data. pthread_cond_wait(&chan->w_cond, &chan->m_mu); - chan->w_waiting--; pthread_mutex_unlock(&chan->m_mu); pthread_mutex_unlock(&chan->w_mu); @@ -353,6 +352,7 @@ static int unbuffered_chan_recv(chan_t* chan, void** data) { *data = chan->data; } + chan->w_waiting--; // Signal waiting writer. pthread_cond_signal(&chan->w_cond);