question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Sync ExecuteReader doesn't stop after calling command.Cancel() when DB connection is lost

See original GitHub issue

Before submitting

Hello! I am stuck with an issue when using the synchronous API in Npgsql in a situation when DB connection is lost. The bottom line is that after calling the command interrupt method (NpgsqlCommand.Cancel), the execution of the NpgsqlCommand.ExecuteReader method is not interrupted (it will be executed until the Command Timeout has passed).

Steps to reproduce

For example, I can attach this code:

class Program
    {
        static void Main(string[] args)
        {
            var connectionString =
                "Server=192.168.135.208;Username=npgsql_tests;Password=npgsql_tests;Database=npgsql_tests;Timeout=30;Command Timeout=180";
            using (var conn = new NpgsqlConnection(connectionString))
            {
                conn.Open();

                using (var cmd = new NpgsqlCommand("SELECT pg_sleep(150)", conn))
                {
                    Task.Factory.StartNew(() =>
                    {
                        Thread.Sleep(1000);
                        try
                        {
                            cmd.Cancel();
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                        }
                    });
                    
                    try
                    {
                        var reader = cmd.ExecuteReader();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
            }
        }
    }

Here is details steps:

  1. Add breakepoint where cmd.Cancel() called
  2. Run the program and stop at the breakepoint image
  3. Emulate loss of DB connection (for example, I use ifdown interface in my virtual machine, or with iptables rule).
  4. See what after calling cmd.Cancel()- cmd.ExecuteReader() still continues execution and will only be stopped after reaching Command Timeout.

In ExecuterReaderAsync this case works correctly. In spite of the connection breaks, the method (ExecuterReaderAsync) call terminates.

The issue

I expect that after the connection is broken and the command close method is called, there will be an immediate execution stop. Maybe, correct way is: https://github.com/npgsql/npgsql/blob/main/src/Npgsql/NpgsqlConnector.cs#L1489

        internal void PerformUserCancellation()
        {
            _userCancellationRequested = true;

            if (AttemptPostgresCancellation && SupportsPostgresCancellation)
            {
                var cancellationTimeout = Settings.CancellationTimeout;
                if (PerformPostgresCancellation() && cancellationTimeout >= 0)
                {
                    if (cancellationTimeout > 0)
                    {
                        UserTimeout = cancellationTimeout;
                        ReadBuffer.Timeout = TimeSpan.FromMilliseconds(cancellationTimeout);
                        ReadBuffer.Cts.CancelAfter(cancellationTimeout);
                    }
                        
                    return;
                }
            }

            UserTimeout = -1;
            //ReadBuffer.Timeout = _cancelImmediatelyTimeout;
            _socket.Shutdown(SocketShutdown.Both);
            ReadBuffer.Cts.Cancel();
        }

use _socket.Shutdown here.

Further technical details

Npgsql version: 5.0.1.1 (or 4.1.3.1) PostgreSQL version: 10.7 (not important) Operating system: Windows 10 (or Fedora 32)

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
rojicommented, Jan 13, 2021

Duplicate of #3187

0reactions
ruslanencommented, Jan 13, 2021

@vonzshik, OK, thank you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Will ExecuteReader(CommandBehavior.CloseConnection) ...
Yes even if it throws an exception it will close the connection. If you do not specify CommandBehavior.CloseConnection and you close the ...
Read more >
Mysql.Data Connection must be valid and open error when ...
I'm fairly new to C#, and I'm completely failing to understand why I keep getting this Connection must be valid and open error...
Read more >
SqlCommand.Cancel Method (System.Data.SqlClient)
Tries to cancel the execution of a SqlCommand. ... Close (implicitly or explicitly) before calling Cancel, and then call Cancel, the cancel command...
Read more >
SqlDataReader Class (System.Data.SqlClient)
The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via...
Read more >
Using parameterized queries to avoid SQL injection
In this article, we will explain what the SQL injection attack is, why it could be hazardous, and how to defend our SQL...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found