diff options
-rw-r--r-- | etc/inc/util.inc | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/etc/inc/util.inc b/etc/inc/util.inc index b720d29..2dad476 100644 --- a/etc/inc/util.inc +++ b/etc/inc/util.inc @@ -187,22 +187,34 @@ function send_multiple_events($cmds) { } function refcount_init($reference) { - $shmid = @shmop_open($reference, "c", 0644, 10); - @shmop_write($shmid, 0, 0); - @shmop_close($shmid); + /* Take out a lock while creating the shared memory, just in case something else tries at the same time. */ + $shm_lck_filename = "shm$reference"; + $shm_lck = lock($shm_lck_filename, LOCK_EX); + $shm_size = 10; + $shmid = shmop_open($reference, "c", 0644, $shm_size); + shmop_write($shmid, str_pad("0", 10, "\x0", STR_PAD_RIGHT), 0); + shmop_close($shmid); + unlock($shm_lck); } function refcount_reference($reference) { try { - $shmid = @shmop_open($reference, "w", 0644, 10); + /* The first time through the shared memory will not be there. */ + /* So suppress the warning here and handle the init in the if. */ + $shmid = @shmop_open($reference, "w", 0, 0); if (!$shmid) { refcount_init($reference); - $shmid = @shmop_open($reference, "w", 0, 0); + $shmid = shmop_open($reference, "w", 0, 0); } - $shm_data = @shmop_read($shmid, 0, 10); - $shm_data = str_pad(intval($shm_data) + 1, 4, "0", STR_PAD_LEFT); - @shmop_write($shmid, $shm_data, 0); - @shmop_close($shmid); + /* Take out a lock across the shared memory read, increment, write sequence to make it atomic. */ + $shm_lck_filename = "shm$reference"; + $shm_lck = lock($shm_lck_filename, LOCK_EX); + $shm_size = shmop_size($shmid); + $shm_data = shmop_read($shmid, 0, $shm_size); + $shm_data = intval($shm_data) + 1; + shmop_write($shmid, str_pad($shm_data, $shm_size, "\x0", STR_PAD_RIGHT), 0); + shmop_close($shmid); + unlock($shm_lck); } catch (Exception $e) { log_error($e->getMessage()); } @@ -214,14 +226,19 @@ function refcount_unreference($reference) { try { /* We assume that the shared memory exists. */ $shmid = @shmop_open($reference, "w", 0, 0); - $shm_data = @shmop_read($shmid, 0, 10); + /* Take out a lock across the shared memory read, decrement, write sequence to make it atomic. */ + $shm_lck_filename = "shm$reference"; + $shm_lck = lock($shm_lck_filename, LOCK_EX); + $shm_size = shmop_size($shmid); + $shm_data = @shmop_read($shmid, 0, $shm_size); $shm_data = intval($shm_data) - 1; if ($shm_data < 0) { //debug_backtrace(); log_error(sprintf(gettext("Reference %s is going negative, not doing unreference."), $reference)); } else - @shmop_write($shmid, str_pad($shm_data, 4, "0", STR_PAD_LEFT), 0); - @shmop_close($shmid); + shmop_write($shmid, str_pad($shm_data, $shm_size, "\x0", STR_PAD_RIGHT), 0); + shmop_close($shmid); + unlock($shm_lck); } catch (Exception $e) { log_error($e->getMessage()); } @@ -1832,4 +1849,4 @@ function setup_library_paths() { } } -?> +?>
\ No newline at end of file |