diff options
author | plumbeo <plumbeo@users.noreply.github.com> | 2016-12-28 02:15:46 +0100 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2017-01-04 14:25:01 -0200 |
commit | 8ebf7ce7d988a989d040196769b0174278b0d031 (patch) | |
tree | 9649c74a14aeba15b841a7a037a8adc4ac731c91 /src/etc | |
parent | 2795722bda1ec743badeb536c524442175adb931 (diff) | |
download | pfsense-8ebf7ce7d988a989d040196769b0174278b0d031.zip pfsense-8ebf7ce7d988a989d040196769b0174278b0d031.tar.gz |
Captive portal: use locking to avoid race conditions between rc.prunecaptiveportal and captiveportal_disconnect_all()
Convert rc.prunecaptiveportal to lock()/unlock()/try_lock() and use the lock to ensure that there aren't race conditions between it and captiveportal_disconnect_all().
(cherry picked from commit d793617ee9b4c3f66575737df3e8f6cf04e7c782)
Diffstat (limited to 'src/etc')
-rw-r--r-- | src/etc/inc/captiveportal.inc | 12 | ||||
-rwxr-xr-x | src/etc/rc.prunecaptiveportal | 18 |
2 files changed, 20 insertions, 10 deletions
diff --git a/src/etc/inc/captiveportal.inc b/src/etc/inc/captiveportal.inc index c404f47..02ec3d8 100644 --- a/src/etc/inc/captiveportal.inc +++ b/src/etc/inc/captiveportal.inc @@ -999,6 +999,16 @@ function captiveportal_disconnect_client($sessionid, $term_cause = 1, $logoutRea function captiveportal_disconnect_all($term_cause = 6, $logoutReason = "DISCONNECT") { global $g, $config, $cpzone, $cpzoneid; + /* check if we're pruning old entries and eventually wait */ + $rcprunelock = try_lock("rcprunecaptiveportal{$cpzone}", 60); + + /* if we still don't have the lock, unlock forcefully and take it */ + if (!$rcprunelock) { + log_error("CP zone ${cpzone}: could not obtain the lock for more than 60 seconds, lock taken forcefully to disconnect all users"); + unlock_force("rcprunecaptiveportal{$cpzone}"); + $rcprunelock = lock("rcprunecaptiveportal{$cpzone}", LOCK_EX); + } + $radiussrvs = captiveportal_get_radius_servers(); $cpdb = captiveportal_read_db(); @@ -1018,6 +1028,8 @@ function captiveportal_disconnect_all($term_cause = 6, $logoutReason = "DISCONNE captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], $logoutReason); } unset($cpdb); + + unlock($rcprunelock); } /* send RADIUS acct stop for all current clients */ diff --git a/src/etc/rc.prunecaptiveportal b/src/etc/rc.prunecaptiveportal index 8e639d9..56cc7f9 100755 --- a/src/etc/rc.prunecaptiveportal +++ b/src/etc/rc.prunecaptiveportal @@ -75,18 +75,16 @@ if (!is_array($config['captiveportal'][$cpzone])) { } $cpzoneid = $config['captiveportal'][$cpzone]['zoneid']; -if (file_exists("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running")) { - $stat = stat("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); - if (time() - $stat['mtime'] >= 120) { - @unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); - } else { - log_error("Skipping CP pruning process because previous/another instance is already running"); - return; - } +$rcprunelock = try_lock("rcprunecaptiveportal{$cpzone}", 3); + +if (!$rcprunelock) { + log_error("Skipping CP pruning process for zone {$cpzone} because previous/another instance is already running"); + unlock_force("rcprunecaptiveportal{$cpzone}"); + return; } -@file_put_contents("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running", ""); captiveportal_prune_old(); -@unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); + +unlock($rcprunelock); ?> |