# matplotlib__matplotlib-26011
# Loki Mode Multi-Agent Patch
# Attempts: 1

--- a/lib/matplotlib/axes/_base.py
+++ b/lib/matplotlib/axes/_base.py
@@ -36,6 +36,7 @@ import matplotlib.ticker as mticker
 import matplotlib.transforms as mtransforms
 
 _log = logging.getLogger(__name__)
+_EMIT_CALLBACK = object()  # Sentinel to emit callback but stop recursion
 
 
 class _axis_method_wrapper:
@@ -3598,11 +3599,16 @@ class _AxesBase(martist.Artist):
             self._stale_viewlim_x = False
         if emit:
             self.callbacks.process('xlim_changed', self)
-            # Call all of the other x-axes that are shared with this one
-            for other in self._shared_x_axes.get_siblings(self):
-                if other is not self:
-                    other.set_xlim(self.viewLim.intervalx,
-                                   emit=False, auto=auto)
+        if emit is not _EMIT_CALLBACK:
+            for other in self._shared_axes["x"].get_siblings(self):
+                if other is not self:
+                    other.set_xlim(self.viewLim.intervalx,
+                                   emit=_EMIT_CALLBACK, auto=auto)
+        elif emit is _EMIT_CALLBACK:
+            # We're being called from a sibling, so emit the callback
+            # but don't propagate further
+            self.callbacks.process('xlim_changed', self)
         self.stale = True
         return left, right
 
@@ -3755,11 +3761,16 @@ class _AxesBase(martist.Artist):
             self._stale_viewlim_y = False
         if emit:
             self.callbacks.process('ylim_changed', self)
-            # Call all of the other y-axes that are shared with this one
-            for other in self._shared_y_axes.get_siblings(self):
-                if other is not self:
-                    other.set_ylim(self.viewLim.intervaly,
-                                   emit=False, auto=auto)
+        if emit is not _EMIT_CALLBACK:
+            for other in self._shared_axes["y"].get_siblings(self):
+                if other is not self:
+                    other.set_ylim(self.viewLim.intervaly,
+                                   emit=_EMIT_CALLBACK, auto=auto)
+        elif emit is _EMIT_CALLBACK:
+            # We're being called from a sibling, so emit the callback
+            # but don't propagate further
+            self.callbacks.process('ylim_changed', self)
         self.stale = True
         return bottom, top