Skip to content
This repository has been archived by the owner on Jan 24, 2021. It is now read-only.

Waiting for TaskCompletionSource blocks other requests #2714

Open
andreasjhkarlsson opened this issue Mar 8, 2017 · 29 comments
Open

Waiting for TaskCompletionSource blocks other requests #2714

andreasjhkarlsson opened this issue Mar 8, 2017 · 29 comments

Comments

@andreasjhkarlsson
Copy link

When waiting for a TaskCompletionSource in an async request handler it seems that all other requests are blocked until the TaskCompletionSource is completed.

Reproducer (tested with SelfHost):

public class SampleModule : Nancy.NancyModule
{
    public SampleModule()
    {
        // Should return after 10 seconds
        Get("/threader", async (p)=>
        {
                
            var resultSource = new TaskCompletionSource<DateTime>();

            var thread = new Thread(
                () =>
                {
                    Thread.Sleep(10000);
                    resultSource.SetResult(DateTime.Now);
                }
            );
            thread.Start();

            var finished = await resultSource.Task;

            return string.Format("Thread finished at: {0}", finished);
        });


        // Should return right away
        Get("/echo", (p) =>
        {
            return "Echo?";
        });
    }
}

If you navigate to /threader in a browser tab and then open another tab and navigate to /echo, /echo won't respond until /threader completes also.

My guess is that it's because the wrapped Task never transitions to the 'Running' state, see: http://stackoverflow.com/questions/14836995/is-there-a-way-of-setting-a-task-driven-via-taskcompletionsource-to-status-runn

Tested with 2.0.0-clinteastwood, apologies if it's fixed in head.

@damianh
Copy link
Member

damianh commented Mar 8, 2017

Does this also happen with OWIN host (HttpListener / WebListener)?

@thecodejunkie thecodejunkie added this to the 2.0-dangermouse milestone Mar 8, 2017
@andreasjhkarlsson
Copy link
Author

No, I just tried with a OwinHost and it does not seem to block other requests.

In fact, after some more testing it seems that all async requests blocks other requests when using Nancy.Hosting.Self. For example:

public class SampleModule : Nancy.NancyModule
{
    public SampleModule()
    {
        // Should return after 10 seconds
        Get("/threader", async (p, ct) =>
        {
            await Task.Delay(10000);

            return string.Format("Thread finished at: {0}", DateTime.Now);
        });

        // Should return right away
        Get("/echo", (p) =>
        {
            return "Echo?";
        });
    }
}

So I guess that core issue is that async blocks on Nancy SelfHost.

@damianh
Copy link
Member

damianh commented Mar 9, 2017 via email

@khellang
Copy link
Member

khellang commented Mar 9, 2017

I think this might be because we're awaiting the request processing here. See this comment on the PR that introduced it. This is a pretty serious bug.

@xt0rted
Copy link
Contributor

xt0rted commented Mar 9, 2017

@khellang want me to send in a pr reverting that one line?

@khellang
Copy link
Member

khellang commented Mar 9, 2017

I think we should get #2697 in first 😄

@davidallyoung
Copy link
Contributor

I just got #2697 fixed from my git gaffe, and we should be able to have this resolved soon:tm: .

@khellang
Copy link
Member

@andreasjhkarlsson Would you be able to pull the latest NuGet package from the MyGet feed and see if you can reproduce this now?

@andreasjhkarlsson
Copy link
Author

2.0.0-Pre1846 still shows the same issue. Full reproducer solution here: https://minfil.org/l2sex6b4bd/reproducer.zip

@thecodejunkie
Copy link
Member

ping @khellang @damianh

@damianh
Copy link
Member

damianh commented Sep 17, 2017

Task.Factory.StartNew(async () =>
{
try
{
while(!this.stop)
{
HttpListenerContext context = await this.listener.GetContextAsync().ConfigureAwait(false);
await this.Process(context).ConfigureAwait(false);
}
}
catch(Exception ex)
{
this.configuration.UnhandledExceptionCallback.Invoke(ex);
throw;
}
});

^This looks fairly broken. It is handling one request at a time. It's not related to the TaskCompletionSource in OP's report per se.

https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.HttpListener/OwinHttpListener.cs#L201-L202
^ Here you can see the MS Owin impl spawns a task for each request but it also does reference counting, "pump limits" etc.

I don't think I've ever used the Nancy.Hosting.Self; I've always used the MS Owin HttpListener host for my self hosting needs. (There is also OwinWebListenerHost).

@NancyFx/most-valued-minions My opinion is to kill Nancy.Hosting.Self package. If it stays it needs a rewrite.

@andreasjhkarlsson In the mean time, use the MSOWIN host. V4 is on the way, so there is some legs left in it.

There is a v4 of owin http listener https://github.com/aspnet/AspNetKatana/milestones

@grumpydev
Copy link
Member

This must have been broken fairlyish recently, it never used to only process one request at a time, but last time I looked at the code was probably pre-asyncawait updates.

@xt0rted
Copy link
Contributor

xt0rted commented Sep 17, 2017

This is from #2548 which is what I had asked about reverting in #2714 (comment)

@davidallyoung
Copy link
Contributor

We actually changed Self Host earlier this year with this PR to resolve it only processing one request at a time with #2697. I might be missing something here though :D

@cemremengu
Copy link
Contributor

cemremengu commented Sep 20, 2017 via email

@damianh
Copy link
Member

damianh commented Sep 21, 2017

Kestrel is nice, but the problem for use is that its public API is based on AspNet's HttpContext which is unfortunate.

@khellang
Copy link
Member

@damianh
Copy link
Member

damianh commented Sep 25, 2017

See the dependency graph? Not pure unfortunately.

@khellang
Copy link
Member

That's nothing. Most of it isn't even used (the HTTP abstractions etc.). I bet you could trim some of the assemblies and it'd still run. And if you're targeting .NET Core 2.0, you already have it all on disk (it's not part of publish)

@jchannon
Copy link
Member

jchannon commented Sep 25, 2017 via email

@dpavsrtrl
Copy link

What's the path to fix this? Self-hosting is useful exactly because it has no dependencies.

@shmutalov
Copy link

Any news?

@bespokebob
Copy link
Contributor

This has already been fixed in #2697

@shmutalov
Copy link

Yep, just tested with latest builds. When it will be published to nuget.org?

@bespokebob
Copy link
Contributor

According to #2872, sometime this week or next.

@nkosi23
Copy link

nkosi23 commented Feb 14, 2019

Has this bug fix been released on NuGet? I mean for 1.x. Just to know the state/limitations of the builds I'm running, I came across this ticket randomly.

@nkosi23
Copy link

nkosi23 commented Feb 15, 2019

Apparently not since the NancyHost options introduced in the commit are not available.

It would be really nice to have a snap 1.X release for Nancy.SelfHost since this is a major bug. The fix is already merged so hopefully releasing should be easy enough.

@nkosi23
Copy link

nkosi23 commented Feb 15, 2019

Pinging @thecodejunkie and @khellang

@nkosi23
Copy link

nkosi23 commented Feb 15, 2019

Just read in #2833 that apparently using the OWIN Self Host has been recommended "for a long time". Unfortunately I haven't seen this recommendation anywhere in the documentation for self hosting. We will try to switch to this SelfHost then, hopefully this will not be disruptive.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests