Mercurial > hg > nginx
comparison src/core/ngx_shmtx.c @ 6080:4296627f385a stable-1.6
Core: fixed a race resulting in extra sem_post()'s.
The mtx->wait counter was not decremented if we were able to obtain the lock
right after incrementing it. This resulted in unneeded sem_post() calls,
eventually leading to EOVERFLOW errors being logged, "sem_post() failed
while wake shmtx (75: Value too large for defined data type)".
To close the race, mtx->wait is now decremented if we obtain the lock right
after incrementing it in ngx_shmtx_lock(). The result can become -1 if a
concurrent ngx_shmtx_unlock() decrements mtx->wait before the added code does.
However, that only leads to one extra iteration in the next call of
ngx_shmtx_lock().
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 04 Feb 2015 16:22:43 +0300 |
parents | 0fce5bb53b2d |
children | 860a1c37f3b2 |
comparison
equal
deleted
inserted
replaced
6079:8e56f649fd0d | 6080:4296627f385a |
---|---|
99 | 99 |
100 if (mtx->semaphore) { | 100 if (mtx->semaphore) { |
101 (void) ngx_atomic_fetch_add(mtx->wait, 1); | 101 (void) ngx_atomic_fetch_add(mtx->wait, 1); |
102 | 102 |
103 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { | 103 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { |
104 (void) ngx_atomic_fetch_add(mtx->wait, -1); | |
104 return; | 105 return; |
105 } | 106 } |
106 | 107 |
107 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | 108 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, |
108 "shmtx wait %uA", *mtx->wait); | 109 "shmtx wait %uA", *mtx->wait); |
172 | 173 |
173 for ( ;; ) { | 174 for ( ;; ) { |
174 | 175 |
175 wait = *mtx->wait; | 176 wait = *mtx->wait; |
176 | 177 |
177 if (wait == 0) { | 178 if ((ngx_atomic_int_t) wait <= 0) { |
178 return; | 179 return; |
179 } | 180 } |
180 | 181 |
181 if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) { | 182 if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) { |
182 break; | 183 break; |