Fix panic when there is no enough memory for a new ringbuffer
This commit is contained in:
parent
490e45a52e
commit
9815523a95
@ -2,8 +2,9 @@ use super::*;
|
|||||||
use util::ring_buf::*;
|
use util::ring_buf::*;
|
||||||
|
|
||||||
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
|
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
|
||||||
|
// TODO: Add F_SETPIPE_SZ in fcntl to dynamically change the size of pipe
|
||||||
pub const PIPE_BUF_SIZE: usize = 2 * 1024 * 1024;
|
// to improve memory efficiency. This value is got from /proc/sys/fs/pipe-max-size on linux.
|
||||||
|
pub const PIPE_BUF_SIZE: usize = 1024 * 1024;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Pipe {
|
pub struct Pipe {
|
||||||
@ -13,7 +14,8 @@ pub struct Pipe {
|
|||||||
|
|
||||||
impl Pipe {
|
impl Pipe {
|
||||||
pub fn new(flags: StatusFlags) -> Result<Pipe> {
|
pub fn new(flags: StatusFlags) -> Result<Pipe> {
|
||||||
let mut ring_buf = RingBuf::new(PIPE_BUF_SIZE);
|
let mut ring_buf =
|
||||||
|
RingBuf::new(PIPE_BUF_SIZE).map_err(|e| errno!(ENFILE, "No memory for new pipes"))?;
|
||||||
// Only O_NONBLOCK and O_DIRECT can be applied during pipe creation
|
// Only O_NONBLOCK and O_DIRECT can be applied during pipe creation
|
||||||
let valid_flags = flags & (StatusFlags::O_NONBLOCK | StatusFlags::O_DIRECT);
|
let valid_flags = flags & (StatusFlags::O_NONBLOCK | StatusFlags::O_DIRECT);
|
||||||
Ok(Pipe {
|
Ok(Pipe {
|
||||||
|
@ -233,7 +233,8 @@ impl UnixSocket {
|
|||||||
}
|
}
|
||||||
let obj = UnixSocketObject::get(path)
|
let obj = UnixSocketObject::get(path)
|
||||||
.ok_or_else(|| errno!(EINVAL, "unix socket path not found"))?;
|
.ok_or_else(|| errno!(EINVAL, "unix socket path not found"))?;
|
||||||
let (channel1, channel2) = Channel::new_pair();
|
// TODO: Mov the buffer allocation to function new to comply with the bahavior of unix
|
||||||
|
let (channel1, channel2) = Channel::new_pair()?;
|
||||||
self.status = Status::Connected(channel1);
|
self.status = Status::Connected(channel1);
|
||||||
obj.push(UnixSocket {
|
obj.push(UnixSocket {
|
||||||
obj: Some(obj.clone()),
|
obj: Some(obj.clone()),
|
||||||
@ -336,9 +337,9 @@ unsafe impl Send for Channel {}
|
|||||||
unsafe impl Sync for Channel {}
|
unsafe impl Sync for Channel {}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
fn new_pair() -> (Channel, Channel) {
|
fn new_pair() -> Result<(Channel, Channel)> {
|
||||||
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE);
|
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE)?;
|
||||||
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE);
|
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE)?;
|
||||||
let channel1 = Channel {
|
let channel1 = Channel {
|
||||||
reader: buf1.reader,
|
reader: buf1.reader,
|
||||||
writer: buf2.writer,
|
writer: buf2.writer,
|
||||||
@ -347,11 +348,13 @@ impl Channel {
|
|||||||
reader: buf2.reader,
|
reader: buf2.reader,
|
||||||
writer: buf1.writer,
|
writer: buf1.writer,
|
||||||
};
|
};
|
||||||
(channel1, channel2)
|
Ok((channel1, channel2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_BUF_SIZE: usize = 1 * 1024 * 1024;
|
// TODO: Add SO_SNDBUF and SO_RCVBUF to set/getsockopt to dynamcally change the size.
|
||||||
|
// This value is got from /proc/sys/net/core/rmem_max and wmem_max that are same on linux.
|
||||||
|
pub const DEFAULT_BUF_SIZE: usize = 208 * 1024;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>> =
|
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>> =
|
||||||
|
@ -14,16 +14,16 @@ pub struct RingBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RingBuf {
|
impl RingBuf {
|
||||||
pub fn new(capacity: usize) -> RingBuf {
|
pub fn new(capacity: usize) -> Result<RingBuf> {
|
||||||
let inner = Arc::new(RingBufInner::new(capacity));
|
let inner = Arc::new(RingBufInner::new(capacity)?);
|
||||||
let reader = RingBufReader {
|
let reader = RingBufReader {
|
||||||
inner: inner.clone(),
|
inner: inner.clone(),
|
||||||
};
|
};
|
||||||
let writer = RingBufWriter { inner: inner };
|
let writer = RingBufWriter { inner: inner };
|
||||||
RingBuf {
|
Ok(RingBuf {
|
||||||
reader: reader,
|
reader: reader,
|
||||||
writer: writer,
|
writer: writer,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,20 +49,22 @@ struct RingBufInner {
|
|||||||
const RING_BUF_ALIGN: usize = 16;
|
const RING_BUF_ALIGN: usize = 16;
|
||||||
|
|
||||||
impl RingBufInner {
|
impl RingBufInner {
|
||||||
fn new(capacity: usize) -> RingBufInner {
|
fn new(capacity: usize) -> Result<RingBufInner> {
|
||||||
|
// Capacity should be power of two as capacity - 1 is used as mask
|
||||||
let capacity = max(capacity, RING_BUF_ALIGN).next_power_of_two();
|
let capacity = max(capacity, RING_BUF_ALIGN).next_power_of_two();
|
||||||
RingBufInner {
|
let buf_layout = Layout::from_size_align(capacity, RING_BUF_ALIGN)?;
|
||||||
buf: unsafe {
|
let buf_ptr = unsafe { alloc(buf_layout) };
|
||||||
let buf_layout = Layout::from_size_align_unchecked(capacity, RING_BUF_ALIGN);
|
if buf_ptr.is_null() {
|
||||||
let buf_ptr = alloc(buf_layout);
|
return_errno!(ENOMEM, "no memory for new ring buffers");
|
||||||
assert!(buf_ptr != ptr::null_mut());
|
}
|
||||||
buf_ptr
|
|
||||||
},
|
Ok(RingBufInner {
|
||||||
|
buf: buf_ptr,
|
||||||
capacity: capacity,
|
capacity: capacity,
|
||||||
head: AtomicUsize::new(0),
|
head: AtomicUsize::new(0),
|
||||||
tail: AtomicUsize::new(0),
|
tail: AtomicUsize::new(0),
|
||||||
closed: AtomicBool::new(false),
|
closed: AtomicBool::new(false),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mask(&self) -> usize {
|
fn get_mask(&self) -> usize {
|
||||||
@ -114,8 +116,8 @@ impl RingBufInner {
|
|||||||
|
|
||||||
impl Drop for RingBufInner {
|
impl Drop for RingBufInner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
let buf_layout = Layout::from_size_align(self.capacity, RING_BUF_ALIGN).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
let buf_layout = Layout::from_size_align_unchecked(self.capacity, RING_BUF_ALIGN);
|
|
||||||
dealloc(self.buf, buf_layout);
|
dealloc(self.buf, buf_layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user