Commits

dirkbaechle committed 09a1545

- added simple test for #2720 (execute with cached targets)
- fixed two typos
- updated list of changes

Comments (0)

Files changed (4)

 
                             Change Log
 
+RELEASE 2.X.X - 
+
+  From Alexey Klimkin:
+  
+    - Fixed the Taskmaster, curing spurious build failures in
+      multi-threaded runs (#2720).
+    
+  From Dirk Baechle:
+  
+    - Improved documentation of command-line variables (#2809).
+    - Fixed scons-doc.py to properly convert main XML files (#2812).
+
 
 RELEASE 2.1.0 - Mon, 09 Sep 2011 20:54:57 -0700
 

src/engine/SCons/Node/FS.py

         so only do thread safe stuff here. Do thread unsafe stuff in
         built().
 
-        Returns true iff the node was successfully retrieved.
+        Returns true if the node was successfully retrieved.
         """
         if self.nocache:
             return None

src/engine/SCons/Node/__init__.py

         so only do thread safe stuff here. Do thread unsafe stuff in
         built().
 
-        Returns true iff the node was successfully retrieved.
+        Returns true if the node was successfully retrieved.
         """
         return 0
 

src/engine/SCons/TaskmasterTests.py

 
     def prepare(self):
         self.prepared = 1
+        self.get_binfo()        
 
     def build(self):
         global built_text
     def remove(self):
         pass
 
+    # The following four methods new_binfo(), del_binfo(),
+    # get_binfo(), clear() as well as its calls have been added
+    # to support the cached_execute() test (issue #2720).
+    # They are full copies (or snippets) of their actual
+    # counterparts in the Node class...
+    def new_binfo(self):
+        binfo = "binfo"
+        return binfo
+
+    def del_binfo(self):
+        """Delete the build info from this node."""
+        try:
+            delattr(self, 'binfo')
+        except AttributeError:
+            pass
+
+    def get_binfo(self):
+        """Fetch a node's build information."""
+        try:
+            return self.binfo
+        except AttributeError:
+            pass
+
+        binfo = self.new_binfo()
+        self.binfo = binfo
+
+        return binfo
+    
+    def clear(self):
+        # The del_binfo() call here isn't necessary for normal execution,
+        # but is for interactive mode, where we might rebuild the same
+        # target and need to start from scratch.
+        self.del_binfo()
+
     def built(self):
         global built_text
         if not self.cached:
             built_text = built_text + " really"
+            
+        # Clear the implicit dependency caches of any Nodes
+        # waiting for this Node to be built.
+        for parent in self.waiting_parents:
+            parent.implicit = None
 
+        self.clear()
+        
     def has_builder(self):
         return not self.builder is None
 
         assert built_text is None, built_text
         assert cache_text == ["n7 retrieved", "n8 retrieved"], cache_text
 
+    def test_cached_execute(self):
+        """Test executing a task with cached targets
+        """
+        # In issue #2720 Alexei Klimkin detected that the previous
+        # workflow for execute() led to problems in a multithreaded build.
+        # We have:
+        #    task.prepare()
+        #    task.execute()
+        #    task.executed()
+        #        -> node.visited()
+        # for the Serial flow, but
+        #    - Parallel -           - Worker -
+        #      task.prepare()
+        #      requestQueue.put(task)
+        #                           task = requestQueue.get()
+        #                           task.execute()
+        #                           resultQueue.put(task)
+        #      task = resultQueue.get()
+        #      task.executed()
+        #        ->node.visited()
+        # in parallel. Since execute() used to call built() when a target
+        # was cached, it could unblock dependent nodes before the binfo got
+        # restored again in visited(). This resulted in spurious
+        # "file not found" build errors, because files fetched from cache would
+        # be seen as not up to date and wouldn't be scanned for implicit
+        # dependencies.
+        #
+        # The following test ensures that execute() only marks targets as cached,
+        # but the actual call to built() happens in executed() only.
+        # Like this, the binfo should still be intact after calling execute()...
+        global cache_text
+
+        n1 = Node("n1")
+        # Mark the node as being cached
+        n1.cached = 1
+        tm = SCons.Taskmaster.Taskmaster([n1])
+        t = tm.next_task()
+        t.prepare()
+        t.execute()
+        assert cache_text == ["n1 retrieved"], cache_text
+        # If no binfo exists anymore, something has gone wrong...
+        has_binfo = hasattr(n1, 'binfo')
+        assert has_binfo == True, has_binfo
+
     def test_exception(self):
         """Test generic Taskmaster exception handling
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.