Nancy icon indicating copy to clipboard operation
Nancy copied to clipboard

Waiting for TaskCompletionSource blocks other requests

Open andreasjhkarlsson opened this issue 7 years ago • 29 comments

When waiting for a TaskCompletionSource<T> 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.

andreasjhkarlsson avatar Mar 08 '17 10:03 andreasjhkarlsson

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

damianh avatar Mar 08 '17 18:03 damianh

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.

andreasjhkarlsson avatar Mar 09 '17 08:03 andreasjhkarlsson

Thank you for checking.

On 9 Mar 2017 9:13 a.m., "Andreas Karlsson" [email protected] wrote:

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.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/NancyFx/Nancy/issues/2714#issuecomment-285283879, or mute the thread https://github.com/notifications/unsubscribe-auth/AADgXD8Pd_ZTaYtQw9SRzDUctaPGVJiZks5rj7TCgaJpZM4MWmO9 .

damianh avatar Mar 09 '17 08:03 damianh

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.

khellang avatar Mar 09 '17 09:03 khellang

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

xt0rted avatar Mar 09 '17 13:03 xt0rted

I think we should get #2697 in first :smile:

khellang avatar Mar 09 '17 15:03 khellang

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

davidallyoung avatar Mar 10 '17 20:03 davidallyoung

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

khellang avatar Mar 11 '17 19:03 khellang

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

andreasjhkarlsson avatar Mar 11 '17 21:03 andreasjhkarlsson

ping @khellang @damianh

thecodejunkie avatar Sep 02 '17 14:09 thecodejunkie

https://github.com/NancyFx/Nancy/blob/ceea69506b9270c94cba231e0bf459897077058b/src/Nancy.Hosting.Self/NancyHost.cs#L127-L142 ^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

damianh avatar Sep 17 '17 20:09 damianh

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.

grumpydev avatar Sep 17 '17 21:09 grumpydev

This is from #2548 which is what I had asked about reverting in https://github.com/NancyFx/Nancy/issues/2714#issuecomment-285353026

xt0rted avatar Sep 17 '17 21:09 xt0rted

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

davidallyoung avatar Sep 17 '17 22:09 davidallyoung

Kestrel is the way to go

On Sep 18, 2017 01:30, "David Young" [email protected] wrote:

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

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/NancyFx/Nancy/issues/2714#issuecomment-330098645, or mute the thread https://github.com/notifications/unsubscribe-auth/ABPNXx99hmxl8ngbMS92X2tuSisFtESAks5sjZ1ogaJpZM4MWmO9 .

cemremengu avatar Sep 20 '17 05:09 cemremengu

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

damianh avatar Sep 21 '17 13:09 damianh

@damianh https://github.com/khellang/KestrelPureOwin 😉

khellang avatar Sep 21 '17 13:09 khellang

See the dependency graph? Not pure unfortunately.

damianh avatar Sep 25 '17 18:09 damianh

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)

khellang avatar Sep 25 '17 21:09 khellang

Depends how you publish ie standalone app

On 25 September 2017 at 22:39, Kristian Hellang [email protected] wrote:

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)

— You are receiving this because you are on a team that was mentioned. Reply to this email directly, view it on GitHub https://github.com/NancyFx/Nancy/issues/2714#issuecomment-332021504, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGapu8OWpZ50tWYiQJGlqCy4a7q8WIXks5smB2CgaJpZM4MWmO9 .

jchannon avatar Sep 25 '17 21:09 jchannon

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

dpavsrtrl avatar Apr 18 '18 14:04 dpavsrtrl

Any news?

shmutalov avatar May 30 '18 11:05 shmutalov

This has already been fixed in #2697

bespokebob avatar May 30 '18 17:05 bespokebob

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

shmutalov avatar May 31 '18 05:05 shmutalov

According to #2872, sometime this week or next.

bespokebob avatar May 31 '18 15:05 bespokebob

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 avatar Feb 14 '19 19:02 nkosi23

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 avatar Feb 15 '19 04:02 nkosi23

Pinging @thecodejunkie and @khellang

nkosi23 avatar Feb 15 '19 04:02 nkosi23

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.

nkosi23 avatar Feb 15 '19 04:02 nkosi23