From 9ce18af5cfc05a872f7800cad2138c606c95aed9 Mon Sep 17 00:00:00 2001 From: hummypkg Date: Sun, 10 Apr 2016 13:24:16 +0000 Subject: [PATCH] improve locking git-svn-id: file:///root/webif/svn/pkg/webif/trunk@2845 2a923420-c742-0410-a762-8d5b09965624 --- CONTROL/control | 2 +- webif/lib/fileops | 110 +++++++++++++++++++++++++++++----------------- webif/lib/lock | 73 +++++++++++++++--------------- 3 files changed, 106 insertions(+), 79 deletions(-) diff --git a/CONTROL/control b/CONTROL/control index 11c985e3..df5717cc 100644 --- a/CONTROL/control +++ b/CONTROL/control @@ -1,7 +1,7 @@ Package: webif Priority: optional Section: web -Version: 1.2.8-15 +Version: 1.2.8-16 Architecture: mipsel Maintainer: af123@hpkg.tv Depends: tcpfix,webif-channelicons(>=1.1.20),lighttpd(>=1.4.39-1),jim(>=0.76-1),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.1-1),hmt(>=2.0.9),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7) diff --git a/webif/lib/fileops b/webif/lib/fileops index b101b763..dc1ed7f4 100644 --- a/webif/lib/fileops +++ b/webif/lib/fileops @@ -56,67 +56,97 @@ proc {file touch} {target {ref ""}} { } proc {file tdelete} {target} { - if {[file isdirectory $target]} { - foreach f [readdir -nocomplain $target] { - file tdelete "$target/$f" + try { + if {[file isdirectory $target]} { + foreach f [readdir -nocomplain $target] { + file tdelete "$target/$f" + } + exec /mod/bin/busybox/rm -rf $target + } else { + exec /mod/bin/trm $target } - exec /mod/bin/busybox/rm -rf $target - } else { - exec /mod/bin/trm $target + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } } proc {file read} {target {bytes 0}} { - if {[file readable $target]} { - set fd [open $target] - if {$bytes} { - set ret [$fd read $bytes] - } else { - set ret [$fd read] + try { + if {[file readable $target]} { + set fd [open $target] + if {$bytes} { + set ret [$fd read $bytes] + } else { + set ret [$fd read] + } + $fd close + return $ret } - $fd close - return $ret + error "Cannot read $target" + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } - error "Cannot read $target" } proc {file write} {target content} { - if {[catch {set fd [open $target w]} msg]} { - error "Open failed, $msg" - } else { - $fd puts -nonewline $content - $fd close + try { + if {[catch {set fd [open $target w]} msg]} { + error "Open failed, $msg" + } else { + $fd puts -nonewline $content + $fd close + } + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } } set ::fileops::locks {} -proc {file lock} {target} { - if {[dict exists $::fileops::locks $target]} { - return 0 - } - if {[catch {set fd [open $target w]} msg]} { - error "open '$target' failed, $msg" - } else { - set ret [$fd lock] - if {$ret == 1} { - set ::fileops::locks($target) $fd - } else { - $fd close +proc {file lock} {{create {}} target} { + try { + if {$create ni {{} -create}} { + error "bad option \"$create\": should be -create" } - return $ret + if {[dict exists $::fileops::locks $target]} { + return 0 + } + if {$create eq "" && ![file exists $target]} { + error "'$target' does not exist" + } elseif {[catch {set fd [open $target w]} msg]} { + error "open '$target' failed, $msg" + } else { + set ret [$fd lock] + if {$ret == 1} { + set ::fileops::locks($target) $fd + } else { + $fd close + } + return $ret + } + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } } proc {file unlock} {target} { - if {[dict exists $::fileops::locks $target]} { - set fd $::fileops::locks($target) - dict unset ::fileops::locks $target - set ret [$fd unlock] - $fd close - return $ret + try { + if {[dict exists $::fileops::locks $target]} { + set fd $::fileops::locks($target) + dict unset ::fileops::locks $target + set ret [$fd unlock] + $fd close + return $ret + } + error "$target was not locked." + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } - error "$target was not locked." } local proc file {cmd args} { diff --git a/webif/lib/lock b/webif/lib/lock index da72034a..70f2312d 100644 --- a/webif/lib/lock +++ b/webif/lib/lock @@ -1,50 +1,47 @@ #!/mod/bin/jimsh -set ::_lock::locks {} - -# For testing, 'ababab' collides with 'b' - -proc ::_lock::hash {id} {{hashes {}}} { - set len [string length $id] - set hash $len - - for {set i 0} {$i < $len} {incr i} { - scan [string index $id $i] "%c" asc - set hash [expr (($hash<<5)^($hash>>27))^$asc]; - } - - set hash [expr (65535 - ($hash % 101))] - - while {[dict exists $hashes $hash] && $hashes($hash) ne $id} { - #puts "Hash collision." - if {[incr hash] > 65535} { set hash 32768 } - } - set hashes($hash) $id - - return $hash -} +set ::lock::locks {} proc acquire_lock {id {timeout 0} {interval 0.2}} { - set port [::_lock::hash $id] - incr timeout [clock seconds] + try { + if {[dict exists $::lock::locks $id]} { + #error "Lock already held" + set lock $::lock::locks($id) + } else { + set file "/var/lock/.webiflock_[system filename $id]" + set fh [open $file w] + set lock [list file $file fh $fh] + set ::lock::locks($id) $lock + } - while {[catch {set socket [\ - socket stream.server "127.0.0.1:$port"]} msg]} { - if {[clock seconds] > $timeout} { return 0 } - sleep $interval + incr timeout [clock seconds] + + while {[$lock(fh) lock] != 1} { + if {[clock seconds] > $timeout} { return 0 } + sleep $interval + } + + return 1 + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } - - set ::_lock::locks($id) $socket - return 1 } proc release_lock {id} { - if {![dict exists $::_lock::locks $id]} { return 0 } - if {[catch {close $::_lock::locks($id)} msg]} { - #puts "Error releasing lock: $msg" - return 0 + try { + if {![dict exists $::lock::locks $id]} { + error "Lock not held." + } + set lock $::lock::locks($id) + + set ret [$lock(fh) unlock] + $lock(fh) close + dict unset ::lock::locks $id + return $ret + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg } - unset ::_lock::locks($id) - return 1 }