Skip to content

Commit 1986cb1

Browse files
authored
Merge pull request sfackler#773 from erikjohnston/avoid_deadlock
Fix deadlock when pipelining statements.
2 parents 3073435 + 844a1bd commit 1986cb1

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

tokio-postgres/src/client.rs

+34-22
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,32 @@ impl Responses {
5454
}
5555
}
5656

57-
struct State {
57+
/// A cache of type info and prepared statements for fetching type info
58+
/// (corresponding to the queries in the [prepare](prepare) module).
59+
#[derive(Default)]
60+
struct CachedTypeInfo {
61+
/// A statement for basic information for a type from its
62+
/// OID. Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_QUERY) (or its
63+
/// fallback).
5864
typeinfo: Option<Statement>,
65+
/// A statement for getting information for a composite type from its OID.
66+
/// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY).
5967
typeinfo_composite: Option<Statement>,
68+
/// A statement for getting information for a composite type from its OID.
69+
/// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY) (or
70+
/// its fallback).
6071
typeinfo_enum: Option<Statement>,
72+
73+
/// Cache of types already looked up.
6174
types: HashMap<Oid, Type>,
62-
buf: BytesMut,
6375
}
6476

6577
pub struct InnerClient {
6678
sender: mpsc::UnboundedSender<Request>,
67-
state: Mutex<State>,
79+
cached_typeinfo: Mutex<CachedTypeInfo>,
80+
81+
/// A buffer to use when writing out postgres commands.
82+
buffer: Mutex<BytesMut>,
6883
}
6984

7085
impl InnerClient {
@@ -82,48 +97,50 @@ impl InnerClient {
8297
}
8398

8499
pub fn typeinfo(&self) -> Option<Statement> {
85-
self.state.lock().typeinfo.clone()
100+
self.cached_typeinfo.lock().typeinfo.clone()
86101
}
87102

88103
pub fn set_typeinfo(&self, statement: &Statement) {
89-
self.state.lock().typeinfo = Some(statement.clone());
104+
self.cached_typeinfo.lock().typeinfo = Some(statement.clone());
90105
}
91106

92107
pub fn typeinfo_composite(&self) -> Option<Statement> {
93-
self.state.lock().typeinfo_composite.clone()
108+
self.cached_typeinfo.lock().typeinfo_composite.clone()
94109
}
95110

96111
pub fn set_typeinfo_composite(&self, statement: &Statement) {
97-
self.state.lock().typeinfo_composite = Some(statement.clone());
112+
self.cached_typeinfo.lock().typeinfo_composite = Some(statement.clone());
98113
}
99114

100115
pub fn typeinfo_enum(&self) -> Option<Statement> {
101-
self.state.lock().typeinfo_enum.clone()
116+
self.cached_typeinfo.lock().typeinfo_enum.clone()
102117
}
103118

104119
pub fn set_typeinfo_enum(&self, statement: &Statement) {
105-
self.state.lock().typeinfo_enum = Some(statement.clone());
120+
self.cached_typeinfo.lock().typeinfo_enum = Some(statement.clone());
106121
}
107122

108123
pub fn type_(&self, oid: Oid) -> Option<Type> {
109-
self.state.lock().types.get(&oid).cloned()
124+
self.cached_typeinfo.lock().types.get(&oid).cloned()
110125
}
111126

112127
pub fn set_type(&self, oid: Oid, type_: &Type) {
113-
self.state.lock().types.insert(oid, type_.clone());
128+
self.cached_typeinfo.lock().types.insert(oid, type_.clone());
114129
}
115130

116131
pub fn clear_type_cache(&self) {
117-
self.state.lock().types.clear();
132+
self.cached_typeinfo.lock().types.clear();
118133
}
119134

135+
/// Call the given function with a buffer to be used when writing out
136+
/// postgres commands.
120137
pub fn with_buf<F, R>(&self, f: F) -> R
121138
where
122139
F: FnOnce(&mut BytesMut) -> R,
123140
{
124-
let mut state = self.state.lock();
125-
let r = f(&mut state.buf);
126-
state.buf.clear();
141+
let mut buffer = self.buffer.lock();
142+
let r = f(&mut buffer);
143+
buffer.clear();
127144
r
128145
}
129146
}
@@ -160,13 +177,8 @@ impl Client {
160177
Client {
161178
inner: Arc::new(InnerClient {
162179
sender,
163-
state: Mutex::new(State {
164-
typeinfo: None,
165-
typeinfo_composite: None,
166-
typeinfo_enum: None,
167-
types: HashMap::new(),
168-
buf: BytesMut::new(),
169-
}),
180+
cached_typeinfo: Default::default(),
181+
buffer: Default::default(),
170182
}),
171183
#[cfg(feature = "runtime")]
172184
socket_config: None,

0 commit comments

Comments
 (0)