Fix bug where timed out socket would register itself when server in backpressure state.

This commit is contained in:
fakeshadow 2021-04-01 00:00:56 +08:00
parent 8becb0db70
commit 51d9d4c776
1 changed files with 28 additions and 20 deletions

View File

@ -238,16 +238,22 @@ impl Accept {
fn process_timer(&self, sockets: &mut Slab<ServerSocketInfo>) { fn process_timer(&self, sockets: &mut Slab<ServerSocketInfo>) {
let now = Instant::now(); let now = Instant::now();
sockets.iter_mut().for_each(|(token, info)| { sockets
// only the ServerSocketInfo have an associate timeout value was de registered. .iter_mut()
if let Some(inst) = info.timeout.take() { // Only the ServerSocketInfo have an associate timeout value was de registered.
if now > inst { .filter(|(token, info)| info.timeout.is_some())
self.register_logged(token, info); .for_each(|(token, info)| {
} else { let inst = info.timeout.take().unwrap();
if now < inst {
info.timeout = Some(inst); info.timeout = Some(inst);
} else if !self.backpressure {
self.register_logged(token, info);
} }
} // Drop the timeout if server is in backpressure and socket timeout is expired.
}); // When server is recovered from backpressure it would register all socket without
// a timeout value so this socket register would be delayed till then.
});
} }
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -301,20 +307,22 @@ impl Accept {
} }
fn maybe_backpressure(&mut self, sockets: &mut Slab<ServerSocketInfo>, on: bool) { fn maybe_backpressure(&mut self, sockets: &mut Slab<ServerSocketInfo>, on: bool) {
if self.backpressure { // Only operate when server is in a different backpressure than the given flag.
if !on { if self.backpressure != on {
if on {
self.backpressure = true;
// TODO: figure out if timing out sockets can be safely de-registered twice.
self.deregister_all(sockets);
} else {
self.backpressure = false; self.backpressure = false;
for (token, info) in sockets.iter_mut() { sockets
if info.timeout.is_some() { .iter_mut()
// socket will attempt to re-register itself when its timeout completes // Only operate on socket without associated timeout.
continue; // Socket info with it would attempt to re-register itself when its timeout
} // expire.
self.register_logged(token, info); .filter(|(_, info)| info.timeout.is_none())
} .for_each(|(token, info)| self.register_logged(token, info));
} }
} else if on {
self.backpressure = true;
self.deregister_all(sockets);
} }
} }