Skip to content

Commit c1c89b6

Browse files
committed
attempt to fix #391 by introducing the fixed waiting timeout; TODO: make the timeout configurable
1 parent cd5c1ff commit c1c89b6

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

src/DryIoc/Container.cs

+22-2
Original file line numberDiff line numberDiff line change
@@ -12010,22 +12010,36 @@ internal object TryGetOrAddViaFactoryDelegate(int id, FactoryDelegate createValu
1201012010
return result;
1201112011
}
1201212012

12013+
internal const uint WaitForItemIsSetTimeout = 5000;
12014+
1201312015
internal static object WaitForItemIsSet(ImMapEntry<object> itemRef)
1201412016
{
12017+
var tickCount = (uint)Environment.TickCount;
12018+
var tickStart = tickCount;
1201512019
#if SUPPORTS_SPIN_WAIT
1201612020
Debug.WriteLine("SpinWaiting!!! ");
1201712021

1201812022
var spinWait = new SpinWait();
1201912023
while (itemRef.Value == NoItem)
12024+
{
1202012025
spinWait.SpinOnce();
12026+
if (tickCount - tickStart > WaitForItemIsSetTimeout)
12027+
Throw.It(Error.WaitForScopedServiceIsCreatedTimeoutExpired, WaitForItemIsSetTimeout);
12028+
tickCount = (uint)Environment.TickCount;
12029+
}
1202112030

1202212031
Debug.WriteLine("SpinWaiting!!! Done");
1202312032
#else
1202412033
Debug.WriteLine("LockWaiting!!! ");
1202512034

1202612035
lock (itemRef)
1202712036
while (itemRef.Value == NoItem)
12037+
{
1202812038
Monitor.Wait(itemRef);
12039+
if (tickCount - tickStart > WaitForItemIsSetTimeout)
12040+
Throw.It(Error.WaitForScopedServiceIsCreatedTimeoutExpired, WaitForItemIsSetTimeout);
12041+
tickCount = (uint)Environment.TickCount;
12042+
}
1202912043

1203012044
Debug.WriteLine("Lock waiting!!! Done");
1203112045
#endif
@@ -13486,8 +13500,14 @@ public static readonly int
1348613500
"Validate found the errors, please check the ContainerException.CollectedExceptions for details."),
1348713501
UnableToInterpretTheNestedLambda = Of(
1348813502
"Unable to interpret the nested lambda with Body:" + NewLine +
13489-
"{0}")
13490-
;
13503+
"{0}"),
13504+
WaitForScopedServiceIsCreatedTimeoutExpired = Of(
13505+
"We have waited for the creation of the scoped service by 'other party' for the {0} ticks without the success." + NewLine +
13506+
"It means that either the 'other party' is the parallel thread wich is started! but unable to create the service for the the provided amount of time." + NewLine +
13507+
"Or more likely we have the undetected recursive dependency and the 'other party' is the same thread." + NewLine +
13508+
"Another reason may be that the previous scoped service resolution is failed with the exception and the exception was CATCHED " + NewLine +
13509+
"but you are trying to proceed resolving the failed service again." + NewLine +
13510+
"That's why for all these reasons we have a timeout to prevent the hanging due the infinite waiting.");
1349113511

1349213512
#pragma warning restore 1591 // "Missing XML-comment"
1349313513

test/DryIoc.IssuesTests/GHIssue391_Deadlock_during_Resolve.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public int Run()
1212
return 1;
1313
}
1414

15-
[Test][Ignore("fixme")]
15+
[Test]
1616
public void Test1()
1717
{
1818
var container = new Container(rules => rules
@@ -33,14 +33,14 @@ public void Test1()
3333
// the missing dependency
3434
// container.Register<ID, D>(Reuse.Singleton);
3535

36-
Assert.Throws<ContainerException>(() => container.Resolve<IA>());
36+
// A -> B -> C -> D(missing)
37+
// \----->
3738

38-
// the second code deadlocks instead of throwing
3939
Assert.Throws<ContainerException>(() => container.Resolve<IA>());
40-
}
4140

42-
// A -> B -> C -> D(missing)
43-
// \----->
41+
var ex = Assert.Throws<ContainerException>(() => container.Resolve<IA>());
42+
Assert.AreSame(Error.NameOf(Error.WaitForScopedServiceIsCreatedTimeoutExpired), ex.ErrorName);
43+
}
4444

4545
public interface IA {}
4646
public interface IB {}

0 commit comments

Comments
 (0)