[70174] trunk/base/src

jmr at macports.org jmr at macports.org
Sat Jul 31 05:57:12 PDT 2010


Revision: 70174
          http://trac.macports.org/changeset/70174
Author:   jmr at 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 "" ""]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20100731/9bf8c4b8/attachment.html>


More information about the macports-changes mailing list