@@ -344,7 +344,7 @@ static MUTEX_T accel_zts_readers_mutex = NULL;
344344static zend_atomic_int accel_zts_readers ;
345345static time_t accel_zts_next_warning ;
346346
347- static bool accel_zts_lock_reader_byte (int type )
347+ static bool accel_zts_lock_reader_byte (int cmd , int type )
348348{
349349 struct flock lock ;
350350
@@ -353,59 +353,39 @@ static bool accel_zts_lock_reader_byte(int type)
353353 lock .l_start = 1 ;
354354 lock .l_len = 1 ;
355355
356- return fcntl (lock_file , F_SETLK , & lock ) != -1 ;
356+ return fcntl (lock_file , cmd , & lock ) != -1 ;
357357}
358358
359- /* Must only be called from RINIT; on success the caller sets ZCG(counted) */
360- static bool accel_zts_reader_enter (void )
359+ /* Adds (+1, only from RINIT) or releases (-1) a reference of the calling thread.
360+ * Does not use ZCG() as it is also called from accel_globals_dtor(). */
361+ static bool accel_zts_readers_add (int delta )
361362{
362363 int count ;
363364
364365#ifndef HAVE_NO_ATOMICS
365- /* the process already holds the reader lock: only a positive count may grow */
366366 count = zend_atomic_int_load_ex (& accel_zts_readers );
367- while (count > 0 ) {
368- if (zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count + 1 )) {
367+ while (count > 0 && count + delta > 0 ) {
368+ if (zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count + delta )) {
369369 return true;
370370 }
371371 }
372372#endif
373373
374374 tsrm_mutex_lock (accel_zts_readers_mutex );
375375 count = zend_atomic_int_load_ex (& accel_zts_readers );
376- /* fails while another process restarts the cache (it holds the write lock) */
377- if (count == 0 && !accel_zts_lock_reader_byte (F_RDLCK )) {
376+ /* waits while another process restarts the cache (it holds the write lock) */
377+ if (count == 0 && !accel_zts_lock_reader_byte (F_SETLKW , F_RDLCK )) {
378378 zend_accel_error (ACCEL_LOG_DEBUG , "UpdateC(+1): %s (%d)" , strerror (errno ), errno );
379379 tsrm_mutex_unlock (accel_zts_readers_mutex );
380380 return false;
381381 }
382- while (!zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count + 1 ));
383- tsrm_mutex_unlock (accel_zts_readers_mutex );
384- return true;
385- }
386-
387- /* Releases one reference; does not use ZCG() as it is also called from accel_globals_dtor() */
388- static void accel_zts_reader_leave (void )
389- {
390- int count ;
391-
392- #ifndef HAVE_NO_ATOMICS
393- count = zend_atomic_int_load_ex (& accel_zts_readers );
394- while (count > 1 ) {
395- if (zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count - 1 )) {
396- return ;
397- }
398- }
399- #endif
400-
401- tsrm_mutex_lock (accel_zts_readers_mutex );
402- count = zend_atomic_int_load_ex (& accel_zts_readers );
403- while (!zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count - 1 ));
404- if (count == 1 ) {
382+ while (!zend_atomic_int_compare_exchange_ex (& accel_zts_readers , & count , count + delta ));
383+ if (count + delta == 0 ) {
405384 /* the last reader of this process; unlock before another thread may relock */
406- accel_zts_lock_reader_byte (F_UNLCK );
385+ accel_zts_lock_reader_byte (F_SETLK , F_UNLCK );
407386 }
408387 tsrm_mutex_unlock (accel_zts_readers_mutex );
388+ return true;
409389}
410390#endif
411391
@@ -417,7 +397,7 @@ static inline zend_result accel_activate_add(void)
417397 INCREMENT (mem_usage );
418398 SHM_PROTECT ();
419399#elif defined(ZTS )
420- /* A thread becomes a reader only in RINIT, see accel_zts_reader_enter (). A request
400+ /* A thread becomes a reader only in RINIT, see accel_zts_readers_add (). A request
421401 * that was not admitted there must not start to use SHM later. */
422402 return FAILURE ;
423403#else
@@ -471,7 +451,7 @@ static inline void accel_unlock_all(void)
471451 * belong to the process, and the SHM write lock (byte 0) and the restart lock
472452 * (byte 2) may be held by other threads. */
473453 if (ZCG (counted )) {
474- accel_zts_reader_leave ( );
454+ accel_zts_readers_add ( -1 );
475455 }
476456#else
477457 if (lock_file == -1 ) {
@@ -1032,32 +1012,34 @@ static inline bool accel_is_inactive(void)
10321012static bool accel_zts_restart_begin (void )
10331013{
10341014 int readers ;
1015+ time_t now ;
10351016
10361017 tsrm_mutex_lock (accel_zts_readers_mutex );
10371018 readers = zend_atomic_int_load_ex (& accel_zts_readers );
1038- if (readers == 0 && accel_zts_lock_reader_byte (F_WRLCK )) {
1019+ if (readers == 0 && accel_zts_lock_reader_byte (F_SETLK , F_WRLCK )) {
10391020 return true;
10401021 }
10411022 tsrm_mutex_unlock (accel_zts_readers_mutex );
10421023
1024+ now = time (NULL );
10431025 if (readers == 0 ) {
1044- /* readers in other processes: keep the force_restart_timeout handling */
1026+ /* readers in other processes: as without ZTS, force_restart_timeout kills them,
1027+ * here with all their threads */
10451028 (void ) accel_is_inactive ();
1046- } else if (ZCG (accel_directives ).force_restart_timeout
1047- && ZCSG (force_restart_time )
1048- && time (NULL ) >= ZCSG (force_restart_time )
1049- && time (NULL ) >= accel_zts_next_warning ) {
1050- /* threads cannot be killed, and this process must not kill itself */
1029+ } else if (ZCG (accel_directives ).force_restart_timeout && ZCSG (force_restart_time )
1030+ && now >= ZCSG (force_restart_time ) && now >= accel_zts_next_warning ) {
1031+ /* Threads cannot be killed and this process must not kill itself: the restart
1032+ * waits for the running requests, new ones run uncached meanwhile */
10511033 zend_accel_error (ACCEL_LOG_WARNING , "Restart delayed for %ld seconds by %d threads of process %d still using the cache" ,
1052- (long )(time ( NULL ) - ZCSG (force_restart_time ) + ZCG (accel_directives ).force_restart_timeout ), readers , getpid ());
1053- accel_zts_next_warning = time ( NULL ) + ZCG (accel_directives ).force_restart_timeout ;
1034+ (long )(now - ZCSG (force_restart_time ) + ZCG (accel_directives ).force_restart_timeout ), readers , getpid ());
1035+ accel_zts_next_warning = now + ZCG (accel_directives ).force_restart_timeout ;
10541036 }
10551037 return false;
10561038}
10571039
10581040static void accel_zts_restart_end (void )
10591041{
1060- accel_zts_lock_reader_byte (F_UNLCK );
1042+ accel_zts_lock_reader_byte (F_SETLK , F_UNLCK );
10611043 accel_zts_next_warning = 0 ;
10621044 tsrm_mutex_unlock (accel_zts_readers_mutex );
10631045}
@@ -2886,7 +2868,7 @@ ZEND_RINIT_FUNCTION(zend_accelerator)
28862868#if defined(ZTS ) && !defined(ZEND_WIN32 )
28872869 /* Under ZTS this is the only place where a request starts to use SHM */
28882870 if (ZCG (accelerator_enabled )) {
2889- if (accel_zts_reader_enter ( )) {
2871+ if (accel_zts_readers_add ( 1 )) {
28902872 ZCG (counted ) = true;
28912873 /* SHM-backed keys may be added to the PCRE cache again */
28922874 ZCG (pcre_reseted ) = false;
@@ -3127,7 +3109,7 @@ static void accel_globals_dtor(zend_accel_globals *accel_globals)
31273109 * all threads from the current one. */
31283110 if (accel_globals -> counted && accel_zts_readers_mutex ) {
31293111 accel_globals -> counted = false;
3130- accel_zts_reader_leave ( );
3112+ accel_zts_readers_add ( -1 );
31313113 }
31323114#endif
31333115 zend_string_free (accel_globals -> key );
0 commit comments