Skip to content

Commit 0041a81

Browse files
committed
fix memoryview avoid double release buffer
1 parent 2740d4b commit 0041a81

File tree

3 files changed

+20
-19
lines changed

3 files changed

+20
-19
lines changed

vm/src/builtins/memory.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
use crossbeam_utils::atomic::AtomicCell;
2020
use itertools::Itertools;
2121
use num_traits::ToPrimitive;
22-
use std::fmt::Debug;
22+
use std::{fmt::Debug, mem::ManuallyDrop};
2323

2424
#[derive(FromArgs)]
2525
pub struct PyMemoryViewNewArgs {
@@ -29,7 +29,8 @@ pub struct PyMemoryViewNewArgs {
2929
#[pyclass(module = false, name = "memoryview")]
3030
#[derive(Debug)]
3131
pub struct PyMemoryView {
32-
buffer: PyBuffer,
32+
// avoid double release when memoryview had released the buffer before drop
33+
buffer: ManuallyDrop<PyBuffer>,
3334
// the released memoryview does not mean the buffer is destoryed
3435
// because the possible another memeoryview is viewing from it
3536
released: AtomicCell<bool>,
@@ -93,7 +94,7 @@ impl PyMemoryView {
9394
let stop = options.len * options.itemsize;
9495
let format_spec = Self::parse_format(&options.format, vm)?;
9596
Ok(PyMemoryView {
96-
buffer,
97+
buffer: ManuallyDrop::new(buffer),
9798
released: AtomicCell::new(false),
9899
start: 0,
99100
stop,
@@ -114,7 +115,7 @@ impl PyMemoryView {
114115
let itemsize = options.itemsize;
115116
let format_spec = Self::parse_format(&options.format, vm)?;
116117
Ok(PyMemoryView {
117-
buffer,
118+
buffer: ManuallyDrop::new(buffer),
118119
released: AtomicCell::new(false),
119120
start: range.start * itemsize,
120121
stop: range.end * itemsize,
@@ -132,7 +133,6 @@ impl PyMemoryView {
132133
#[pymethod]
133134
pub fn release(&self) {
134135
if self.released.compare_exchange(false, true).is_ok() {
135-
self.buffer.manually_release = true;
136136
self.buffer.release();
137137
}
138138
}
@@ -689,6 +689,12 @@ impl AsBuffer for PyMemoryView {
689689
}
690690
}
691691

692+
impl Drop for PyMemoryView {
693+
fn drop(&mut self) {
694+
self.release();
695+
}
696+
}
697+
692698
impl AsMapping for PyMemoryView {
693699
fn as_mapping(_zelf: &PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
694700
PyMappingMethods {

vm/src/protocol/buffer.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
};
1313
use std::{borrow::Cow, fmt::Debug};
1414

15+
#[allow(clippy::type_complexity)]
1516
pub struct BufferMethods {
1617
// always reflecting the whole bytes of the most top object
1718
pub obj_bytes: fn(&PyBuffer) -> BorrowedValue<[u8]>,
@@ -45,8 +46,6 @@ impl Debug for BufferMethods {
4546
pub struct PyBuffer {
4647
pub obj: PyObjectRef,
4748
pub options: BufferOptions,
48-
// if true, don't call release when drop
49-
pub manually_release: bool,
5049
methods: &'static BufferMethods,
5150
}
5251

@@ -55,7 +54,6 @@ impl PyBuffer {
5554
let zelf = Self {
5655
obj,
5756
options,
58-
manually_release: false,
5957
methods,
6058
};
6159
zelf.retain();
@@ -193,9 +191,7 @@ impl TryFromBorrowedObject for PyBuffer {
193191
// but it is not supported by Rust
194192
impl Drop for PyBuffer {
195193
fn drop(&mut self) {
196-
if !self.manually_release {
197-
self.release();
198-
}
194+
self.release();
199195
}
200196
}
201197

vm/src/stdlib/io.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -876,9 +876,12 @@ mod _io {
876876
} else {
877877
let v = std::mem::take(&mut self.buffer);
878878
let writebuf = VecBuffer::new(v).into_ref(vm);
879-
let memobj =
880-
PyMemoryView::from_buffer_range(writebuf.clone().into_readonly_pybuffer(), buf_range, vm)?
881-
.into_ref(vm);
879+
let memobj = PyMemoryView::from_buffer_range(
880+
writebuf.clone().into_readonly_pybuffer(),
881+
buf_range,
882+
vm,
883+
)?
884+
.into_ref(vm);
882885

883886
// TODO: loop if write() raises an interrupt
884887
let res = vm.call_method(self.raw.as_ref().unwrap(), "write", (memobj.clone(),));
@@ -3286,11 +3289,7 @@ mod _io {
32863289
len: self.buffer.read().cursor.get_ref().len(),
32873290
..Default::default()
32883291
};
3289-
let buffer = PyBuffer::new(
3290-
self.clone().into_object(),
3291-
options,
3292-
&BYTES_IO_BUFFER_METHODS,
3293-
);
3292+
let buffer = PyBuffer::new(self.into_object(), options, &BYTES_IO_BUFFER_METHODS);
32943293
let view = PyMemoryView::from_buffer(buffer, vm)?;
32953294
Ok(view)
32963295
}

0 commit comments

Comments
 (0)