Skip to content

Property Injection with AllowCircularDependencies occurs too late; concurrency error #1200

@alistairjevans

Description

@alistairjevans

In v6, this test fails:

[Fact]
public async Task WhenSeveralThreadsTryToAccessSharedPropertyInjectedInstance()
{
    for (var i = 0; i < 200; i++)
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<A>();
        builder.RegisterType<B>().SingleInstance().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
        var container = builder.Build();

        var t1 = Task.Run(() => container.Resolve<B>().AssertProp());
        var t2 = Task.Run(() => container.Resolve<B>().AssertProp());
        var t3 = Task.Run(() => container.Resolve<B>().AssertProp());
        var t4 = Task.Run(() => container.Resolve<B>().AssertProp());

        await Task.WhenAll(t1, t2, t3, t4);
    }
}

private sealed class B
{
    public A Prop { get; set; }

    public void AssertProp()
    {
        if (Prop is null)
        {
            throw new NullReferenceException();
        }
    }
}

This occurs because, in v6, property injection that permits circular dependency injection occurs in the RequestCompleting event, which fires at the end of the operation, after the synchronised shared instance activation; meaning that some of the requests will complete before property injection has finished.

This needs to be fixed, probably by moving the point in the pipeline that circular dependency detection happens to later, so we can more easily attach to before it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions