修复一处内存泄漏问题

This commit is contained in:
MeiK 2021-02-12 01:41:51 +08:00
parent ffb6a69f3f
commit 19489557d3
3 changed files with 27 additions and 19 deletions

View File

@ -7,7 +7,5 @@
## TODO
- 解决偶发性的 `wait4 failure` 问题
- 解决偶发性的内存测量不精确问题
- 解决内存占用已经超出限制时,未能结束进程,从而结果表现为 TLE 的问题
- 修复 Rust 无法编译的问题
- 修复貌似内存泄漏的问题

View File

@ -13,6 +13,7 @@ RUN apt-get install -y software-properties-common && add-apt-repository -y ppa:d
# install rust
RUN apt-get install -y curl && curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y
ENV PATH="/root/.cargo/bin:${PATH}"
RUN rustup default stable
# install node
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs
@ -35,5 +36,3 @@ RUN add-apt-repository -y ppa:longsleep/golang-backports && apt-get install -y g
RUN apt-get install -y default-jdk
RUN rm -rf /var/lib/apt/lists/*
RUN rustup default stable

View File

@ -70,22 +70,45 @@ impl Process {
}
}
// 为 clone 的栈所需的指针创建 Send 与 Sync 包装
// 因为 Rust 编译器不允许原始的 c_void 在线程间同步
// 我们可以创建一个包装来规避这个问题,但前提是我们需要明白我们在做什么
struct Stack {
stack: *const libc::c_void,
}
unsafe impl Send for Stack {}
unsafe impl Sync for Stack {}
pub struct Runner {
process: Process,
pid: i32,
tx: Arc<Mutex<mpsc::Sender<RunnerStatus>>>,
rx: Arc<Mutex<mpsc::Receiver<RunnerStatus>>>,
stack: Stack,
cgroup_set: CGroupSet,
}
impl Runner {
pub fn from(process: Process) -> Result<Runner> {
let (tx, rx) = mpsc::channel();
let stack = unsafe {
libc::mmap(
ptr::null_mut(),
STACK_SIZE,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK,
-1,
0,
)
};
debug!("mmap stack");
Ok(Runner {
process: process,
pid: -1,
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
stack: Stack { stack: stack },
cgroup_set: CGroupSet::new()?,
})
}
@ -107,6 +130,8 @@ impl Drop for Runner {
fn drop(&mut self) {
debug!("dropping");
unsafe {
libc::munmap(self.stack.stack as *mut libc::c_void, STACK_SIZE);
debug!("munmap stack");
killpid(self.pid);
}
}
@ -118,24 +143,13 @@ impl Future for Runner {
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<RunnerStatus>> {
let runner = Pin::into_inner(self);
let time_limit = (runner.process.time_limit / 1000 + 1) as u64 * 2;
// 创建 clone 所需的栈空间
let stack = unsafe {
libc::mmap(
ptr::null_mut(),
STACK_SIZE,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK,
-1,
0,
)
};
// 如果 pid == -1则说明子进程还没有运行
if runner.pid == -1 {
let waker = cx.waker().clone();
let pid = unsafe {
libc::clone(
runit,
(stack as usize + STACK_SIZE) as *mut libc::c_void,
(runner.stack.stack as usize + STACK_SIZE) as *mut libc::c_void,
libc::SIGCHLD
| libc::CLONE_NEWUTS // 设置新的 UTS 名称空间(主机名、网络名等)
| libc::CLONE_NEWNET // 设置新的网络空间,如果没有配置网络,则该沙盒内部将无法联网
@ -175,9 +189,6 @@ impl Future for Runner {
});
return Poll::Pending;
} else {
unsafe {
libc::munmap(stack, STACK_SIZE);
}
let mut status = runner.rx.lock().unwrap().recv().unwrap();
let mem_used = match runner
.cgroup_set