mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-19 04:26:39 +00:00
Block when incoming_conns
reaches backlog
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
e555d8c616
commit
069cd7932b
@ -1,6 +1,5 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use super::{connected::Connected, listener::push_incoming};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{IoEvents, Observer},
|
events::{IoEvents, Observer},
|
||||||
fs::{
|
fs::{
|
||||||
@ -44,10 +43,6 @@ impl Init {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn connect(&self, remote_addr: &UnixSocketAddrBound) -> Result<Connected> {
|
|
||||||
push_incoming(remote_addr, self.addr.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn addr(&self) -> Option<&UnixSocketAddrBound> {
|
pub(super) fn addr(&self) -> Option<&UnixSocketAddrBound> {
|
||||||
self.addr.as_ref()
|
self.addr.as_ref()
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ impl Backlog {
|
|||||||
|
|
||||||
if incoming_conns.len() >= self.backlog.load(Ordering::Relaxed) {
|
if incoming_conns.len() >= self.backlog.load(Ordering::Relaxed) {
|
||||||
return_errno_with_message!(
|
return_errno_with_message!(
|
||||||
Errno::ECONNREFUSED,
|
Errno::EAGAIN,
|
||||||
"the pending connection queue on the listening socket is full"
|
"the pending connection queue on the listening socket is full"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,11 @@ use core::sync::atomic::AtomicBool;
|
|||||||
|
|
||||||
use atomic::Ordering;
|
use atomic::Ordering;
|
||||||
|
|
||||||
use super::{connected::Connected, init::Init, listener::Listener};
|
use super::{
|
||||||
|
connected::Connected,
|
||||||
|
init::Init,
|
||||||
|
listener::{push_incoming, Listener},
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{IoEvents, Observer},
|
events::{IoEvents, Observer},
|
||||||
fs::{
|
fs::{
|
||||||
@ -23,6 +27,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::signal::{Pollable, Poller},
|
process::signal::{Pollable, Poller},
|
||||||
|
thread::Thread,
|
||||||
util::IoVec,
|
util::IoVec,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -221,8 +226,8 @@ impl Socket for UnixStreamSocket {
|
|||||||
//
|
//
|
||||||
// See also <https://elixir.bootlin.com/linux/v6.10.4/source/net/unix/af_unix.c#L1527>.
|
// See also <https://elixir.bootlin.com/linux/v6.10.4/source/net/unix/af_unix.c#L1527>.
|
||||||
|
|
||||||
let connected = match &*self.state.read() {
|
let client_addr = match &*self.state.read() {
|
||||||
State::Init(init) => init.connect(&remote_addr)?,
|
State::Init(init) => init.addr().cloned(),
|
||||||
State::Listen(_) => {
|
State::Listen(_) => {
|
||||||
return_errno_with_message!(Errno::EINVAL, "the socket is listening")
|
return_errno_with_message!(Errno::EINVAL, "the socket is listening")
|
||||||
}
|
}
|
||||||
@ -231,8 +236,23 @@ impl Socket for UnixStreamSocket {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
*self.state.write() = State::Connected(connected);
|
// We use the `push_incoming` directly to avoid holding the read lock of `self.state`
|
||||||
Ok(())
|
// because it might call `Thread::yield_now` to wait for connection.
|
||||||
|
loop {
|
||||||
|
let res = push_incoming(&remote_addr, client_addr.clone());
|
||||||
|
match res {
|
||||||
|
Ok(connected) => {
|
||||||
|
*self.state.write() = State::Connected(connected);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Err(err) if err.error() == Errno::EAGAIN => {
|
||||||
|
// FIXME: Calling `Thread::yield_now` can cause the thread to run when the backlog is full,
|
||||||
|
// which wastes a lot of CPU time. Using `WaitQueue` maybe a better solution.
|
||||||
|
Thread::yield_now()
|
||||||
|
}
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn listen(&self, backlog: usize) -> Result<()> {
|
fn listen(&self, backlog: usize) -> Result<()> {
|
||||||
|
Reference in New Issue
Block a user