New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Seemingly random NullReferenceException in async state machine #234
Comments
Do you have repro code? |
Unfortunately, no. This is supported in .NET Framework only. |
@sakno I added you to a small reproduction repo in our organization. I guess you should be notified with a link, if not tell me please. When you run it you can see that the resulting DTO has all the "steps" but each step has only one change although it should have multiple. If you set a breakpoint in the catch handler of the Hope you can figure things out with this :) Thanks for the help! Tip: Using https://github.com/MapsterMapper/ExpressionDebugger I managed to at least get a bit more information out of it. Using Rider I could step into most parts (except the generated method unfortunately). Helps a lot. It then also actually hit an exception breakpoint itself when the mapping was done where you could do a single step and land inside the |
I see the link, thanks. The problem is that I need an isolated repro code to convert it into the test. |
Ah okay. Well, it's hard to say what is required to reproduce it. Not sure what can be stripped and how a test for that should look like... I'll try to strip everything around it as much as possible. |
Alright, I removed everything that is not needed. Still reproduces. Should be few enough to convert it into a test, I hope. Can you work with that now? |
Reproduced with the following test: [Fact]
public static async Task RegressionIssue234()
{
var method1 = typeof(LambdaTests).GetMethod(nameof(DoNothingAsync), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
var method2 = typeof(LambdaTests).GetMethod(nameof(DoYieldAsync), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
var lambda = AsyncLambda<Func<Task<int>>>((ctx, result) =>
{
Await(Expression.Call(method2));
Await(Expression.Call(method1));
Assign(result, 42.Const());
}).Compile();
for (var i = 0; i < 100; i++)
{
Equal(42, await lambda.Invoke());
}
}
private static Task DoNothingAsync() => Task.CompletedTask;
private static async Task DoYieldAsync()
{
await Task.Yield();
} |
Wonderful, good to hear it helped you nail it down to a small test :) I'm really curious as to what is causing this issue. I couldn't identify any issue in the control flow yet. Btw: You should maybe consider adding some kind of donation option to your repository (if just for a coffee) ;) |
It's fixed. Could you check it from
|
Moreover, when |
Looks splendid, works like a charm. I really expected it to be more, but it makes perfect sense that a pooled state machine might be reused before it should be. Thank you very much! |
Release 5.3.1 has been published |
For our DTO mappings I generate an async method that builds a proxy around a generic base implementation. Basically it takes the untyped version of a source model, casts it into it's actual model, passes it to the base method and then returns the generic DTO instead of a specific implementation of it.
So far so good, the method itself works. The odd issue is that when I run the compiled method against multiple models of the same type it sometimes fails with a
NullReferenceException
and sometimes it does not. I added logging instructions and null-checks in the generated method to be sure nothing is null. I checked before calling the method and also added try-catch handlers in the methods that are called from inside this generated method.From the exception I don't get any information as to what could be the reason. By now I eliminated all sources I could possibly see and guess it might be an issue in the generated state machine itself.
@sakno Is there a way to debug the generated output? Some way to generate PDBs for it so I can step into the methods? Or is there any other way I can trace this down? I would guess there must be a slight oversight as dotnext seems to be well tested and established. But I can't find the source of this exception and stack traces are not really helpful:
I can provide you with the lambda body if needed to check the generated state machine. Or whatever information you need.
The text was updated successfully, but these errors were encountered: