diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py
index b8bc741..b4cf7ec 100644
--- a/django/template/loader_tags.py
+++ b/django/template/loader_tags.py
@@ -1,4 +1,4 @@
-from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
+from django.template import TemplateSyntaxError, Variable
 from django.template import Library, Node, TextNode
 from django.template.loader import get_template
 from django.conf import settings
@@ -7,8 +7,12 @@ from django.utils.safestring import mark_safe
 register = Library()
 
 BLOCK_CONTEXT_KEY = 'block_context'
+EXTENDS_SEEN_KEY = 'extends_seen_parents'
 
-class ExtendsError(Exception):
+class ExtendsError(TemplateSyntaxError):
+    pass
+
+class ExtendsRecursionError(ExtendsError):
     pass
 
 class BlockContext(object):
@@ -94,9 +98,18 @@ class ExtendsNode(Node):
             error_msg = "Invalid template name in 'extends' tag: %r." % parent
             if self.parent_name_expr:
                 error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token
-            raise TemplateSyntaxError(error_msg)
+            raise ExtendsError(error_msg)
         if hasattr(parent, 'render'):
             return parent # parent is a Template object
+        if EXTENDS_SEEN_KEY not in context.render_context:
+            seen_parents = set()
+            context.render_context[EXTENDS_SEEN_KEY] = seen_parents 
+        else:
+            seen_parents = context.render_context[EXTENDS_SEEN_KEY]
+            if parent in seen_parents:
+                raise ExtendsRecursionError('Template %r cannot be extended '
+                        'because it would cause a circular recursion' % parent)
+        seen_parents.add(parent)
         return get_template(parent)
 
     def render(self, context):
@@ -109,8 +122,9 @@ class ExtendsNode(Node):
         # Add the block nodes from this node to the block context
         block_context.add_blocks(self.blocks)
 
-        # If this block's parent doesn't have an extends node it is the root,
-        # and its block nodes also need to be added to the block context.
+        # If this template's parent doesn't have an extends node it is the root
+        # then the parent's block nodes also need to be added to the block
+        # context.
         for node in compiled_parent.nodelist:
             # The ExtendsNode has to be the first non-text node.
             if not isinstance(node, TextNode):
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 5902e8d..e13623b 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -15,7 +15,7 @@ import unittest
 
 from django import template
 from django.core import urlresolvers
-from django.template import loader
+from django.template import loader, loader_tags
 from django.template.loaders import app_directories, filesystem, cached
 from django.utils.translation import activate, deactivate, ugettext as _
 from django.utils.safestring import mark_safe
@@ -642,7 +642,7 @@ class Templates(unittest.TestCase):
             'exception01': ("{% extends 'nonexistent' %}", {}, template.TemplateDoesNotExist),
 
             # Raise exception for invalid template name (in variable)
-            'exception02': ("{% extends nonexistent %}", {}, (template.TemplateSyntaxError, template.TemplateDoesNotExist)),
+            'exception02': ("{% extends nonexistent %}", {}, (loader_tags.ExtendsError, template.TemplateDoesNotExist)),
 
             # Raise exception for extra {% extends %} tags
             'exception03': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}", {}, template.TemplateSyntaxError),
@@ -1041,6 +1041,24 @@ class Templates(unittest.TestCase):
             'inheritance40': ("{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': 1}, '1new23'),
             'inheritance41': ("{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}", {'numbers': '123'}, '_new1_new2_new3_'),
 
+            ### CIRCULAR INHERITANCE EXCEPTIONS #######################################
+
+            # Self-extending template
+            'circularinheritance01': ("{% extends 'circularinheritance01' %}", {}, loader_tags.ExtendsRecursionError),
+
+            # Circular extending template
+            'circularinheritance02': ("{% extends 'circularinheritance04' %}", {}, loader_tags.ExtendsRecursionError),
+            'circularinheritance03': ("{% extends 'circularinheritance02' %}", {}, loader_tags.ExtendsRecursionError),
+            'circularinheritance04': ("{% extends 'circularinheritance03' %}", {}, loader_tags.ExtendsRecursionError),
+
+            # Self-extending template (by variable)
+            'circularinheritance05': ("{% extends var %}", {'var': 'circularinheritance05'}, loader_tags.ExtendsRecursionError),
+
+            # Circular template (by variable)
+            'circularinheritance06': ("{% extends var %}", {'var': 'circularinheritance08'}, loader_tags.ExtendsRecursionError),
+            'circularinheritance07': ("{% extends var %}", {'var': 'circularinheritance06'}, loader_tags.ExtendsRecursionError),
+            'circularinheritance08': ("{% extends var %}", {'var': 'circularinheritance07'}, loader_tags.ExtendsRecursionError),
+
             ### I18N ##################################################################
 
             # {% spaceless %} tag
