Skip to content

Commit 5f8fc6b

Browse files
jpmelosmadadam
andauthored
Pool.close: close all connections before returning (#3952)
* fix race condition in pool close (#3217) * fix deadlock in the postgres/listen example * Only acquire as many permits as a child pool can offer --------- Co-authored-by: Adam Cigánek <[email protected]>
1 parent ed002f8 commit 5f8fc6b

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

examples/postgres/listen/src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
6868
}
6969
}
7070

71+
// The stream is holding one connection. It needs to be dropped to allow the connection to
72+
// return to the pool, otherwise `pool.close()` would never return.
73+
drop(stream);
74+
7175
pool.close().await;
7276

7377
Ok(())

sqlx-core/src/pool/inner.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,24 @@ impl<DB: Database> PoolInner<DB> {
9797
self.mark_closed();
9898

9999
async move {
100-
for permits in 1..=self.options.max_connections {
101-
// Close any currently idle connections in the pool.
102-
while let Some(idle) = self.idle_conns.pop() {
103-
let _ = idle.live.float((*self).clone()).close().await;
104-
}
100+
// For child pools, we need to acquire permits we actually have rather than
101+
// max_connections
102+
let permits_to_acquire = if self.options.parent_pool.is_some() {
103+
// Child pools start with 0 permits, so we acquire based on current size
104+
self.size()
105+
} else {
106+
// Parent pools can acquire all max_connections permits
107+
self.options.max_connections
108+
};
105109

106-
if self.size() == 0 {
107-
break;
108-
}
110+
let _permits = self.semaphore.acquire(permits_to_acquire).await;
109111

110-
// Wait for all permits to be released.
111-
let _permits = self.semaphore.acquire(permits).await;
112+
while let Some(idle) = self.idle_conns.pop() {
113+
let _ = idle.live.raw.close().await;
112114
}
115+
116+
self.num_idle.store(0, Ordering::Release);
117+
self.size.store(0, Ordering::Release);
113118
}
114119
}
115120

0 commit comments

Comments
 (0)