(&mut self, payload: &[u8])
| 1229 | } |
| 1230 | |
| 1231 | fn send_protocol_inner(&mut self, payload: &[u8]) -> Result<Vec<u8>> { |
| 1232 | self.reset_backend_c_timings()?; |
| 1233 | |
| 1234 | { |
| 1235 | let _phase = timing::phase("postgres.protocol.input_reset"); |
| 1236 | self.io.reset(&mut self.store)?; |
| 1237 | } |
| 1238 | { |
| 1239 | let _phase = timing::phase("postgres.protocol.input_write"); |
| 1240 | self.io |
| 1241 | .push_input(&mut self.store, &self.env, &self.guest_allocator, payload)?; |
| 1242 | } |
| 1243 | |
| 1244 | { |
| 1245 | let _phase = timing::phase("postgres.protocol.dispatch_buffer"); |
| 1246 | let max_attempts = (payload.len() / 5).saturating_add(2).max(1); |
| 1247 | let mut attempts = 0usize; |
| 1248 | let mut recovered_protocol_error = false; |
| 1249 | while self.protocol_input_remaining()? > 0 { |
| 1250 | attempts += 1; |
| 1251 | ensure!( |
| 1252 | attempts <= max_attempts, |
| 1253 | "Postgres protocol dispatch did not drain buffered input after {attempts} attempts" |
| 1254 | ); |
| 1255 | if let Err(err) = self.protocol.main_loop.call(&mut self.store) { |
| 1256 | if runtime_error_exit_code(&err) == Some(POSTGRES_MAIN_LONGJMP) { |
| 1257 | debug!( |
| 1258 | "PostgresMainLoopOnce used host longjmp fallback; recovering protocol error" |
| 1259 | ); |
| 1260 | self.recover_protocol_error(payload.len())?; |
| 1261 | recovered_protocol_error = true; |
| 1262 | } else if is_wasm_uncaught_exception(&err) { |
| 1263 | debug!( |
| 1264 | "PostgresMainLoopOnce trapped for PostgreSQL error; recovering protocol state: {err}" |
| 1265 | ); |
| 1266 | self.recover_protocol_error(payload.len())?; |
| 1267 | recovered_protocol_error = true; |
| 1268 | } else { |
| 1269 | warn!("PostgresMainLoopOnce trapped; attempting protocol recovery: {err}"); |
| 1270 | self.recover_protocol_error(payload.len())?; |
| 1271 | recovered_protocol_error = true; |
| 1272 | } |
| 1273 | } |
| 1274 | } |
| 1275 | |
| 1276 | { |
| 1277 | let _phase = timing::phase("postgres.protocol.send_ready"); |
| 1278 | self.protocol |
| 1279 | .send_ready |
| 1280 | .call(&mut self.store) |
| 1281 | .context("PostgresSendReadyForQueryIfNecessary")?; |
| 1282 | } |
| 1283 | { |
| 1284 | let _phase = timing::phase("postgres.protocol.pq_flush"); |
| 1285 | self.protocol |
| 1286 | .pq_flush |
| 1287 | .call(&mut self.store) |
| 1288 | .context("pgl_pq_flush after protocol buffer")?; |
no test coverage detected