Index: test/test_multitask.rb
===================================================================
--- test/test_multitask.rb	(revision 602)
+++ test/test_multitask.rb	(working copy)
@@ -40,6 +40,15 @@
     assert @runs.index("B0") < @runs.index("B1")
     assert @runs.index("B1") < @runs.index("B2")
   end
+
+  def test_multitasks_maintain_seperate_depenency_stacks
+    @stack_a = @stack_b = nil
+    task :a do |t| @stack_a = t.stack; end
+    task :b do |t| @stack_b = t.stack; end
+    multitask :both => [:a, :b]
+    Task[:both].invoke
+    assert_not_same(@stack_a, @stack_b)
+  end
 end
 
  
Index: test/test_tasks.rb
===================================================================
--- test/test_tasks.rb	(revision 602)
+++ test/test_tasks.rb	(working copy)
@@ -39,6 +39,17 @@
     assert_equal ["t2", "t3", "t1"], runlist
   end
 
+  def test_invoke_with_circular_dependencies
+    runlist = []
+    t1 = intern(:t1).enhance([:t2]) { |t| runlist << t.name; 3321 }
+    t2 = intern(:t2).enhance([:t1]) { |t| runlist << t.name }
+    assert_equal [:t2], t1.prerequisites
+    assert_equal [:t1], t2.prerequisites
+    assert_raises(RuntimeError) do
+      t1.invoke
+    end
+  end
+
   def test_dry_run_prevents_actions
     Rake.application.options.dryrun = true
     runlist = []
Index: lib/rake.rb
===================================================================
--- lib/rake.rb	(revision 602)
+++ lib/rake.rb	(working copy)
@@ -391,17 +391,28 @@
     
     # Invoke the task if it is needed.  Prerequites are invoked first.
     def invoke
+      fail "Circular dependency " + (stack + [name]).join("=>") if stack.include?(name)
       @lock.synchronize do
         if application.options.trace
           puts "** Invoke #{name} #{format_trace_flags}"
         end
         return if @already_invoked
-        @already_invoked = true
-        invoke_prerequisites
-        execute if needed?
+        begin
+          stack.push name
+          @already_invoked = true
+          invoke_prerequisites
+          execute if needed?
+        ensure
+          stack.pop
+        end
       end
     end
 
+    # A stack containing the history of previously run rake tasks
+    def stack
+      Thread.current[:rake_stack] ||= []
+    end
+
     # Invoke all the prerequisites of a task.
     def invoke_prerequisites
       @prerequisites.each { |n|
