diff --git a/core/circuit/circuit.go b/core/circuit/circuit.go index 6a06d69a4..85ebea6ec 100644 --- a/core/circuit/circuit.go +++ b/core/circuit/circuit.go @@ -148,6 +148,12 @@ func (c *Circuit) GetParent() api.Circuit { // setParent set parent circuit func (c *Circuit) setParent(parent api.Circuit) error { + // prevent cyclical dependency + for p := parent.GetParent(); p != nil; p = p.GetParent() { + if c == p { + return fmt.Errorf("cycle detected: %s and %s cannot be mutual parents", c.GetTitle(), parent.GetTitle()) + } + } c.mu.Lock() defer c.mu.Unlock() if c.parent != nil { diff --git a/core/circuit/circuit_test.go b/core/circuit/circuit_test.go index 172ad176d..d48765bab 100644 --- a/core/circuit/circuit_test.go +++ b/core/circuit/circuit_test.go @@ -139,3 +139,13 @@ func TestCircuitCurrents(t *testing.T) { ctrl.Finish() } } + +func TestWrapCycleDetection(t *testing.T) { + log := util.NewLogger("foo") + + pc, _ := New(log, "root", 0, 0, nil, 0) + lpc, _ := New(log, "lpc", 0, 0, nil, 0) + + require.NoError(t, lpc.setParent(pc)) + require.Error(t, pc.Wrap(lpc)) +}