Revision: 70174 http://trac.macports.org/changeset/70174 Author: jmr@macports.org Date: 2010-07-31 05:57:09 -0700 (Sat, 31 Jul 2010) Log Message: ----------- acquire an exclusive lock when making registry modifications (#19935) Modified Paths: -------------- trunk/base/src/macports1.0/macports.tcl trunk/base/src/port/port.tcl trunk/base/src/registry2.0/registry.tcl Modified: trunk/base/src/macports1.0/macports.tcl =================================================================== --- trunk/base/src/macports1.0/macports.tcl 2010-07-31 12:42:05 UTC (rev 70173) +++ trunk/base/src/macports1.0/macports.tcl 2010-07-31 12:57:09 UTC (rev 70174) @@ -1584,7 +1584,7 @@ # Before we build the port, we must build its dependencies. set dlist {} if {[macports::_target_needs_deps $target]} { - + registry::exclusive_lock # see if we actually need to build this port if {($target != "activate" && $target != "install") || ![$workername eval registry_exists \$name \$version \$revision \$portvariants]} { @@ -1638,6 +1638,7 @@ } else { set result [dlist_eval $dlist _mportinstalled [list _mportexec "activate"]] } + registry::exclusive_unlock if {$result != {}} { set errstring "The following dependencies failed to build:" Modified: trunk/base/src/port/port.tcl =================================================================== --- trunk/base/src/port/port.tcl 2010-07-31 12:42:05 UTC (rev 70173) +++ trunk/base/src/port/port.tcl 2010-07-31 12:57:09 UTC (rev 70174) @@ -4066,6 +4066,24 @@ } } +# acquire exclusive registry lock for actions that need it +# returns 1 if locked, 0 otherwise +proc lock_reg_if_needed {action} { + switch -- $action { + activate - + deactivate - + select - + setrequested - + unsetrequested - + upgrade - + uninstall - + install { + registry::exclusive_lock + return 1 + } + } + return 0 +} proc process_cmd { argv } { global cmd_argc cmd_argv cmd_argn @@ -4092,7 +4110,8 @@ while { [moreargs] } { advance } break } - + + set locked [lock_reg_if_needed $action] # Always start out processing an action in current_portdir cd $current_portdir @@ -4155,6 +4174,11 @@ # execute the action set action_status [$action_proc $action $portlist [array get global_options]] + # unlock if needed + if {$locked} { + registry::exclusive_unlock + } + # semaphore to exit if {$action_status == -999} break } Modified: trunk/base/src/registry2.0/registry.tcl =================================================================== --- trunk/base/src/registry2.0/registry.tcl 2010-07-31 12:42:05 UTC (rev 70173) +++ trunk/base/src/registry2.0/registry.tcl 2010-07-31 12:57:09 UTC (rev 70174) @@ -39,6 +39,8 @@ package require msgcat namespace eval registry { + variable lockfd + variable nlocked 0 # Begin creating a new registry entry for the port version_revision+variant # This process assembles the directory name and creates a receipt dlist @@ -387,6 +389,49 @@ return [${macports::registry.format}::write_dep_map $args] } +# acquire exclusive lock on registry, do this before modifying it or reading +# any info which will affect a decision on what to modify +proc exclusive_lock {} { + global macports::registry.path + variable lockfd + variable nlocked + incr nlocked + if {$nlocked > 1} { + return + } + set lockpath [file join ${registry.path} registry .registry.lock] + if {![info exists lockfd]} { + set lockfd [::open $lockpath w] + } + if {[catch {flock $lockfd -exclusive -noblock} result]} { + if {$result == "EAGAIN"} { + ui_msg "Waiting for lock on $lockpath" + flock $lockfd -exclusive + } elseif {$result == "EOPNOTSUPP"} { + # Locking not supported, just return + ui_debug "flock not supported, not locking registry" + } else { + return -code error "$result obtaining lock on $lockpath" + } + } +} + +# release exclusive lock on registry, do this when done writing to it +proc exclusive_unlock {} { + variable lockfd + variable nlocked + incr nlocked -1 + if {$nlocked > 0} { + return + } elseif {$nlocked < 0} { + ui_warn "exclusive_unlock called more often than exclusive_lock!" + } + if {[info exists lockfd]} { + # not much point trying to handle errors + catch {flock $lockfd -unlock} + } +} + # upgrade flat receipts to registry2.0 sqlite db proc convert_to_sqlite {} { set ilist [receipt_flat::installed "" ""]
participants (1)
-
jmr@macports.org