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
Tests crashing with Assertion failed: PostgresConnection deinitialized before being closed.
#2810
Comments
I'm seeing this as well. The conditions in my case are simpler, though: during a test, I was creating a very large number of connections intentionally, by running a bunch of transactions on tasks created inside a let app = Application(.testing)
defer { app.shutdown() }
try await configure(app)
await withThrowingTaskGroup(of: Void.self, body: { group in
for _ in 0..<500 {
group.addTask {
try await app.db.transaction { … }
}
}
}
See next comment. |
Nevermind, by logging things at trace level, I realized it's my mistake. 🤦♂️ So I was removing something from the database as the last step of the test. However, I did it on a defer block, like this: defer { let _ = x.delete(force: true, on: app.db) } What I didn't realize is this is not the async call, but the one that returns the Replacing that by a proper async call fixed the issue. Apologies for all the noise. 😔 |
So I'm able to repeat the same error when I test an async function that includes a For some reason, when I use the async version of Function being tested:
Non Working Test Version:
In the above version I get Working Test Version (the only difference is the
|
I think the problem in this case is that you're launching an unstructured concurrency If you need an "async defer", maybe this here can help: https://gist.github.com/finestructure/500d9fda7dfc99400e8ef5bddb38776b. This will tack the defer on to the end of your function and part of its "await", so to speak. You can then leave it up to the caller if you want to "fire and forget" it by wrapping it in an unstructured |
We've started tracking an issue in the Swift Package Index about test flakiness around four weeks ago. When running tests under certain conditions, we're hitting the assert
in PostgresNIO/PostgresConnection.swift:153. This seems to be happening when the
Application
is shutdown after a test, which we do as follows in each test:It's important to note that we originally saw this issue triggering the assert
in Vapor/Application.swift:164. This changed to the
PostgresConnection
assert over the course of debugging this issue but I suspect both of these have the same underlying cause. Since I can't be sure this is the case, I wanted to raise this issue at the API level where we first observed it and where more people would see it.I've prepared a standalone repo "DebugTestRace" which is a minimally modified template Vapor project exposing the issue.
The file AppTests.swift contains the reproducer with an enum
Variants
controlling which core test to run.This is relevant, because there seem to be a number of conditions that need to be met in order to trigger the issue and I wanted to make it easy to observe them side by side with some passing variants. The conditions are:
EventLoopFuture
s need to be in flight..notFound
exception viaunwrap
(or perhaps any other exception needs to be thrown via some mechanism).EventLoopFuture
is resolved in an async/await context viatry await elf.get()
.usleep
before theapp.shutdown
avoids triggering the assert regardless of any or all of the above conditions being met.The way to expose the issue is to run all the tests in
AppTests
which is just running the same test function_test
over and over 50 times. This should trigger the assertion for the two variantstriggerAssertWithAnotherELF
andtriggerAssertWithELFAnd
.Make sure to run
make db-up
andmake migrate
to launch and set up the dockerised test db.For what it's worth, there's some evidence that the speed of the machine executing the tests is relevant. I can typically trigger the assertion via the
DebugTestRace
project on my M1 Max MacBook Pro within a single run of all tests for the two failing variants. Only rarely do all tests for these pass.We're currently working around these crashes by inserting strategic
usleep
calls but we'll probably be able to work around it by converting the underlying functions toasync
.Any help tracking this down is greatly appreciated, in particular if there's anything wrong with our setup (which is of course entirely possible!).
The text was updated successfully, but these errors were encountered: