-
Notifications
You must be signed in to change notification settings - Fork 39
Unhandled Exceptions causes PgConnection.close
to hang forever (v3)
#119
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
Comments
That's worth investigating! I think we should check-in such tests into the repo with skip: true, so CI would pass, but it will be there for anybody to look into. There should be a different naming though, like Note: I've just pushed the above test under the |
I just looked a bit into this and here is what I found: For reference, according to PostgreSQL docs SEVERITY-LEVELS, both postgresql-dart/lib/src/connection_fsm.dart Lines 21 to 24 in 18b22c5
In v3, this is not handled in a variety of places. I observed two scenarios:
Also, while looking into the issue, I found some other weak spots. For instance, in simple query with ignore rows, I got unhandled exceptions such as As for the postgresql-dart/lib/src/v3/connection.dart Lines 371 to 380 in 18b22c5
In short, whenever a Another thought about fatal errors, assuming the hanging problem was solved, how should the user know that the connection was terminated? Once they try to execute a query? Or should there be an One final thought -- any reason why |
Thanks a lot for the investigation @osaxma!! I've fixed the problematic handling of error messages in #126, that should also add the
It's actually hanging because the
That's a good point - we could expose a
How was the timeout implemented in v2? The places I've checked (not all of them) just applied a timeout to the returned future, which would continue to block the connection when a query takes longer than the timeout, right? Is there a way to reliably cancel queries after a timeout is reached? |
Oh my bad -- I thought the queue was empty but apparently I was looking at the wrong member in
I just looked at where the timeout was handled in v2. It looks like the query is removed from the queue if it times out and nothing much ( postgresql-dart/lib/src/connection.dart Lines 617 to 640 in 18b22c5
... apparently it's not straightforward according to 55.2.8. Canceling Requests in Progress: "To issue a cancel request, the frontend opens a new connection to the server and sends a CancelRequest message, rather than the StartupMessage message that would ordinarily be sent across a new connection" |
This test (using same setup as in first comment) should reproduce the test('Simple Protocol - fatal error', () async {
// Get the PID for conn1
final res = await conn2
.execute("SELECT pid FROM pg_stat_activity where usename = 'dart';");
final conn1PID = res.first.first as int;
// ignore: unawaited_futures
final future =
conn1.execute('select * from pg_stat_activity;', ignoreRows: true);
await conn2.execute(
'select pg_terminate_backend($conn1PID) from pg_stat_activity;');
}); >>>> Logs <<<<
|
I believe this issue has been fully addressed. Thanks @simolus3 for the fixes! |
Add the following code to a file in the test folder and run it to reproduce the issue (or read the comments in the code):
I think currently there's no direct and easy way for the user to handle such Exceptions (maybe a callback would help?). I also think
PgConnection.close
should check if the connection was closed/terminated/errored-out before trying a graceful termination process.Additional Context
I initially encountered a simple issue where
await conn.close();
would hang forever due to a connection blocking query used in logical replication (i.e.START_REPLICATION ......
). I tried to force close the connection but there was no way around it. So I opened a separate connection to kill the replication process in the database in the testingteardown
code as a workaround. That's when I came across the issue which is presented in the code snippet above.While this issue appeared with me in an edge case, I still think there should be a way to handle such severe/fatal PostgreSQL errors because they may appear in other cases. Also, as mentioned earlier, the
PgConnection.close
should account for such scenarios and maybe have a flag for ungraceful termination (e.g.PgConnection.close(force: true)
) in addition to a timeout logic (honestly i didn't try to add timeout settings yet).cc: @isoos @simolus3
The text was updated successfully, but these errors were encountered: