user584018
user584018

Reputation: 11364

Is deadlock or application hung state possible for ASP.NET Core Web API application

I have an ASP.NET Core 3.1 Web API application which has a background host service where I wrote below code to simulate deadlock for the application:

public class Worker : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        var a = new object();
        var b = new object();

        lock (a)
        {
            lock (b)
            {
            }
        }

        // other thread
        lock (b)
        {
            lock (a)
            {
            }
        }

        return Task.CompletedTask;
    }
}

The app is running, but the app is NOT going to deadlock or hung state, I can still hit the web api end point and result is back to me.

Will it be possible to make the running web app into deadlock or hung state, so that NONE of the API give any 200 result?

Thanks.

Upvotes: 3

Views: 820

Answers (2)

Metro Smurf
Metro Smurf

Reputation: 38385

As written, the current method will NEVER deadlock.

The lock objects are local to the method. Correct locking must use an object outside the scope of the method.

In the following revision, the lock objects are static to the class, and the locking adds a tiny delay to simulate work being performed. In this scenario, the app will deadlock with the 2nd entrance of the method.

public class Worker
{
    private static readonly object _a = new();
    private static readonly object _b = new();
    private const int _delay = 5;

    public Task StartAsync2( int n )
    {
        lock( _a )
        {
            Console.WriteLine( $"{n}: _a1 enter" );
            lock( _b )
            {
                Console.WriteLine( $"{n}: _b1 enter" );
                Thread.Sleep( _delay );
            }
            Console.WriteLine( $"{n}: _b1 exit" );
        }
        Console.WriteLine( $"{n}: _a1 exit" );

        // other thread
        lock( _b )
        {
            Console.WriteLine( $"{n}: _b2 enter" );
            lock( _a )
            {
                Console.WriteLine( $"{n}: _a2 enter" );
                Thread.Sleep( _delay );
            }
            Console.WriteLine( $"{n}: _a2 exit" );
        }
        Console.WriteLine( $"{n}: _b2 exit" );

        return Task.CompletedTask;
    }
}

And here's how to execute the Worker to cause a deadlock:

var w = new Worker();
var t = new Task[5];

for( int i = 0; i < t.Length; i++ )
{
    int n = i;
    t[i] = Task.Run( () =>
    {
        Console.WriteLine( $"{n} start" );
        w.StartAsync2( n );
        Console.WriteLine( $"{n} end" );

        return Task.CompletedTask;
    } );
}

Task.WaitAll( t );

Upvotes: 2

Raymond Hartoyo
Raymond Hartoyo

Reputation: 266

Not sure about ASP.NET, based on your code example, you can try to utilize something like Thread sleep / delay so that each thread doesn't lock the resource too fast.

probably something like:

        lock (a)
        {
            Thread.sleep(..duration..)

            lock (b)
            {
            }
        }

        // other thread
        lock (b)
        {
            Thread.sleep(..duration..)

            lock (a)
            {
            }
        }

Upvotes: 0

Related Questions