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::*;
|
||||
|
||||
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
|
||||
|
||||
pub const PIPE_BUF_SIZE: usize = 2 * 1024 * 1024;
|
||||
// TODO: Add F_SETPIPE_SZ in fcntl to dynamically change the size of pipe
|
||||
// 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)]
|
||||
pub struct Pipe {
|
||||
@ -13,7 +14,8 @@ pub struct Pipe {
|
||||
|
||||
impl 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
|
||||
let valid_flags = flags & (StatusFlags::O_NONBLOCK | StatusFlags::O_DIRECT);
|
||||
Ok(Pipe {
|
||||
|
@ -233,7 +233,8 @@ impl UnixSocket {
|
||||
}
|
||||
let obj = UnixSocketObject::get(path)
|
||||
.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);
|
||||
obj.push(UnixSocket {
|
||||
obj: Some(obj.clone()),
|
||||
@ -336,9 +337,9 @@ unsafe impl Send for Channel {}
|
||||
unsafe impl Sync for Channel {}
|
||||
|
||||
impl Channel {
|
||||
fn new_pair() -> (Channel, Channel) {
|
||||
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||
fn new_pair() -> Result<(Channel, Channel)> {
|
||||
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE)?;
|
||||
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE)?;
|
||||
let channel1 = Channel {
|
||||
reader: buf1.reader,
|
||||
writer: buf2.writer,
|
||||
@ -347,11 +348,13 @@ impl Channel {
|
||||
reader: buf2.reader,
|
||||
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! {
|
||||
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>> =
|
||||
|
@ -14,16 +14,16 @@ pub struct RingBuf {
|
||||
}
|
||||
|
||||
impl RingBuf {
|
||||
pub fn new(capacity: usize) -> RingBuf {
|
||||
let inner = Arc::new(RingBufInner::new(capacity));
|
||||
pub fn new(capacity: usize) -> Result<RingBuf> {
|
||||
let inner = Arc::new(RingBufInner::new(capacity)?);
|
||||
let reader = RingBufReader {
|
||||
inner: inner.clone(),
|
||||
};
|
||||
let writer = RingBufWriter { inner: inner };
|
||||
RingBuf {
|
||||
Ok(RingBuf {
|
||||
reader: reader,
|
||||
writer: writer,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,20 +49,22 @@ struct RingBufInner {
|
||||
const RING_BUF_ALIGN: usize = 16;
|
||||
|
||||
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();
|
||||
RingBufInner {
|
||||
buf: unsafe {
|
||||
let buf_layout = Layout::from_size_align_unchecked(capacity, RING_BUF_ALIGN);
|
||||
let buf_ptr = alloc(buf_layout);
|
||||
assert!(buf_ptr != ptr::null_mut());
|
||||
buf_ptr
|
||||
},
|
||||
let buf_layout = Layout::from_size_align(capacity, RING_BUF_ALIGN)?;
|
||||
let buf_ptr = unsafe { alloc(buf_layout) };
|
||||
if buf_ptr.is_null() {
|
||||
return_errno!(ENOMEM, "no memory for new ring buffers");
|
||||
}
|
||||
|
||||
Ok(RingBufInner {
|
||||
buf: buf_ptr,
|
||||
capacity: capacity,
|
||||
head: AtomicUsize::new(0),
|
||||
tail: AtomicUsize::new(0),
|
||||
closed: AtomicBool::new(false),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_mask(&self) -> usize {
|
||||
@ -114,8 +116,8 @@ impl RingBufInner {
|
||||
|
||||
impl Drop for RingBufInner {
|
||||
fn drop(&mut self) {
|
||||
let buf_layout = Layout::from_size_align(self.capacity, RING_BUF_ALIGN).unwrap();
|
||||
unsafe {
|
||||
let buf_layout = Layout::from_size_align_unchecked(self.capacity, RING_BUF_ALIGN);
|
||||
dealloc(self.buf, buf_layout);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user