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;