We're seeing occasional CircularDependencyExceptions being reported when
using Dependency Injection.  By spurious I mean that 1 out of every say
10,000 requests to get() an instance of a given class will fail with that
exception being thrown, while the rest of them will work fine.

I dug into the code today to see how that could happen, and found that it's
triggered by 1) using the DI container to get an instance of some class C,
during which in one of the recursive calls to Di->get() or
Di->newInstance() some dependent class D's instantiator throws an
exception, and 2) doing a subsequent Di->get() for D, C, or any other class
that depends on D.

The cause is that in case of (1), proper cleanup is not done on the
Di::$currentDependencies variable when an exception is thrown, and thus
it's left in an unclean state (with some dependencies vs. empty), so that
during (2), Di->resolveMethodParameters() spuriously thinks there's a
circular dependency.

The fix would be to put a try/catch block around the code that pushes/pops
Di::$currentDependencies and does recursive calls, and in the catch block
reset Di::$currentDependencies before re-throwing the exception.  Maybe
there's other cleanup that should be done there too, but this is the one
we've been bitten by.

thx,
Chris

Reply via email to