RustPython: bug: Double Free On `BufferedReader`&`FileIO`?

Bug behavior

Added a is_drop field in PyInner. and found out both BufferedReader&FileIO gets double drop? Did some search on the code, no clue where misses a clone() to PyRef or PyObjectRef

Possible root of bug

a obscure memcpy on a struct containing a PyRef/PyObjectRef

Necessity of fixing the bug

Useful for writing garbage collecting, also prevent UB

Part of the log

the remaining of log file just basically repeats those lines. The command is just cargo run, and alright it did run, but with all those double drop: log_buf.log

[ERROR rustpython_vm::object::core] Double drop on PyRef, type="rustpython_vm::stdlib::io::_io::BufferedReader"
[ERROR rustpython_vm::object::core] Double drop on PyRef, type="rustpython_vm::stdlib::io::fileio::FileIO"
[ERROR rustpython_vm::object::core] Double drop on PyObjectRef, typeid=TypeId { t: 14576741135102236696 }, type=Some("rustpython_vm::stdlib::io::fileio::FileIO")
[ERROR rustpython_vm::object::core] Double drop on PyRef, type="rustpython_vm::stdlib::io::_io::BufferedReader"
                    backtrace=   0: <rustpython_vm::object::core::PyRef<T> as core::ops::drop::Drop>::drop
                 at vm/src/object/core.rs:979:17
       1: core::ptr::drop_in_place<rustpython_vm::object::core::PyRef<rustpython_vm::stdlib::io::_io::BufferedReader>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
       2: rustpython_vm::stdlib::io::_io::BufferedMixin::close
                 at vm/src/stdlib/io.rs:1575:9
       3: core::ops::function::Fn::call
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:77:5
       4: rustpython_vm::function::builtin::<impl rustpython_vm::function::builtin::sealed::PyNativeFuncInternal<(rustpython_vm::function::builtin::OwnedParam<T1>,),R,rustpython_vm::vm::VirtualMachine> for F>::call_
                 at vm/src/function/builtin.rs:79:17
       5: <F as rustpython_vm::function::builtin::IntoPyNativeFunc<(T,R,VM)>>::call
                 at vm/src/function/builtin.rs:47:9
          rustpython_vm::function::builtin::IntoPyNativeFunc::into_func::{{closure}}
                 at vm/src/function/builtin.rs:35:51
       6: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc/src/boxed.rs:1886:9
       7: <rustpython_vm::builtins::builtinfunc::PyBuiltinMethod as rustpython_vm::types::slot::Callable>::call
                 at vm/src/builtins/builtinfunc.rs:210:9
       8: rustpython_vm::types::slot::Callable::slot_call
                 at vm/src/types/slot.rs:562:13
       9: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
                 at vm/src/vm/vm_object.rs:176:30
      10: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
                 at vm/src/vm/vm_object.rs:189:9
          rustpython_vm::vm::method::PyMethod::invoke
                 at vm/src/vm/method.rs:121:9
      11: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::call_method
                 at vm/src/vm/vm_object.rs:127:9
      12: <rustpython_vm::stdlib::io::_io::_IOBase as rustpython_vm::types::slot::Destructor>::slot_del
                 at vm/src/stdlib/io.rs:541:21
      13: rustpython_vm::object::core::PyObject::drop_slow_inner::call_slot_del::{{closure}}
                 at vm/src/object/core.rs:768:33
      14: rustpython_vm::vm::thread::with_vm::{{closure}}
                 at vm/src/vm/thread.rs:38:14
      15: std::thread::local::LocalKey<T>::try_with
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:445:16
      16: std::thread::local::LocalKey<T>::with
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:421:9
      17: rustpython_vm::vm::thread::with_vm
                 at vm/src/vm/thread.rs:27:5
      18: rustpython_vm::object::core::PyObject::drop_slow_inner::call_slot_del
                 at vm/src/object/core.rs:766:23
      19: rustpython_vm::object::core::PyObject::drop_slow_inner
                 at vm/src/object/core.rs:789:13
          rustpython_vm::object::core::PyObject::drop_slow
                 at vm/src/object/core.rs:801:26
      20: <rustpython_vm::object::core::PyObjectRef as core::ops::drop::Drop>::drop
                 at vm/src/object/core.rs:871:22
      21: core::ptr::drop_in_place<rustpython_vm::object::core::PyObjectRef>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      22: core::ptr::drop_in_place<core::option::Option<rustpython_vm::object::core::PyObjectRef>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      23: core::ptr::drop_in_place<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      24: core::ptr::drop_in_place<alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      25: core::ptr::drop_in_place<core::cell::UnsafeCell<alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      26: core::ptr::drop_in_place<lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex,alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      27: core::ptr::drop_in_place<rustpython_vm::frame::Frame>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      28: core::ptr::drop_in_place<rustpython_vm::object::core::PyInner<rustpython_vm::frame::Frame>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      29: core::ptr::drop_in_place<alloc::boxed::Box<rustpython_vm::object::core::PyInner<rustpython_vm::frame::Frame>>>
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
      30: core::mem::drop
                 at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/mem/mod.rs:974:24
      31: rustpython_vm::object::core::drop_dealloc_obj
                 at vm/src/object/core.rs:89:5
      32: rustpython_vm::object::core::PyObject::drop_slow
                 at vm/src/object/core.rs:807:9

Test Code

added is_drop field to PyInner<T> in core.rs This is the git diff patch file(Also added a backtrace crate for debugging in this patch)

drop_guard.patch.txt

And here is core code to check double dropping:

diff --git a/vm/src/object/core.rs b/vm/src/object/core.rs
index 19055df25..0eed91f4a 100644
--- a/vm/src/object/core.rs
+++ b/vm/src/object/core.rs
@@ -31,6 +31,7 @@ use std::{
     any::TypeId,
     borrow::Borrow,
     cell::UnsafeCell,
+    collections::HashMap,
     fmt,
     marker::PhantomData,
     mem::ManuallyDrop,
@@ -38,6 +39,11 @@ use std::{
     ptr::{self, NonNull},
 };
 
+use once_cell::sync::Lazy;
+
+pub static ID2TYPE: Lazy<PyMutex<HashMap<TypeId, String>>> =
+    Lazy::new(|| PyMutex::new(HashMap::new()));
+
 // so, PyObjectRef is basically equivalent to `PyRc<PyInner<dyn PyObjectPayload>>`, except it's
 // only one pointer in width rather than 2. We do that by manually creating a vtable, and putting
 // a &'static reference to it inside the `PyRc` rather than adjacent to it, like trait objects do.
@@ -109,6 +115,7 @@ impl PyObjVTable {
 #[repr(C)]
 struct PyInner<T> {
     ref_count: RefCount,
+    is_drop: PyMutex<bool>,
     // TODO: move typeid into vtable once TypeId::of is const
     typeid: TypeId,
     vtable: &'static PyObjVTable,
@@ -433,6 +440,7 @@ impl<T: PyObjectPayload> PyInner<T> {
         let member_count = typ.slots.member_count;
         Box::new(PyInner {
             ref_count: RefCount::new(),
+            is_drop: PyMutex::new(false),
             typeid: TypeId::of::<T>(),
             vtable: PyObjVTable::of::<T>(),
             typ: PyAtomicRef::from(typ),
@@ -849,7 +857,15 @@ impl<'a, T: PyObjectPayload> From<&'a Py<T>> for &'a PyObject {
 impl Drop for PyObjectRef {
     #[inline]
     fn drop(&mut self) {
+        if *self.0.is_drop.lock() {
+            error!(
+                "Double drop on PyObjectRef, typeid={:?}, type={:?}",
+                self.0.typeid,
+                ID2TYPE.lock().get(&self.0.typeid)
+            );
+        }
         if self.0.ref_count.dec() {
+            *self.0.is_drop.lock() = true;
             unsafe { PyObject::drop_slow(self.ptr) }
         }
     }
@@ -953,7 +969,21 @@ impl<T: PyObjectPayload> fmt::Debug for PyRef<T> {
 impl<T: PyObjectPayload> Drop for PyRef<T> {
     #[inline]
     fn drop(&mut self) {
+        if *self.as_object().0.is_drop.lock() {
+            error!(
+                "Double drop on PyRef, type={:?}",
+                std::any::type_name::<T>()
+            );
+        }
+
+        let tid = TypeId::of::<T>();
+        ID2TYPE
+            .lock()
+            .entry(tid)
+            .or_insert_with(|| std::any::type_name::<T>().to_string());
+
         if self.0.ref_count.dec() {
+            *self.0.is_drop.lock() = true;
             unsafe { PyObject::drop_slow(self.ptr.cast::<PyObject>()) }
         }
     }
@@ -1136,6 +1166,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
         let type_type_ptr = Box::into_raw(Box::new(partially_init!(
             PyInner::<PyType> {
                 ref_count: RefCount::new(),
+                is_drop: PyMutex::new(false),
                 typeid: TypeId::of::<PyType>(),
                 vtable: PyObjVTable::of::<PyType>(),
                 dict: None,
@@ -1148,6 +1179,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
         let object_type_ptr = Box::into_raw(Box::new(partially_init!(
             PyInner::<PyType> {
                 ref_count: RefCount::new(),
+                is_drop: PyMutex::new(false),
                 typeid: TypeId::of::<PyType>(),
                 vtable: PyObjVTable::of::<PyType>(),
                 dict: None,

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (18 by maintainers)

Most upvoted comments

one thing to check? is it called from once as FileIO and another once as _RawIOBase?

This is by no means my final solution, but I found if I elide a drop call in _IOBase then everything is going to be fine, no double drop or whatever (although I don’t know whether there is leak in anywhere):

impl _IOBase{
...
        #[pymethod(magic)]
        fn exit(instance: PyObjectRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
            vm.call_method(&instance, "close", ())?;
            let _ = ManuallyDrop::new(instance);
            Ok(())
        }
...
}

Edited: eliding instance’drop() in _IOBase’s flush also “works”

There is one extra call to BufferedMixin’s close() from Frame’s fastlocal’s drop, but still can’t figure out why would the ref count be missing

The first deref of a PyObjectRef/PyRef to a dropped object is from _IOBase’s slot_del function, which, I assume, run _IOBase’s __del__ fn for BufferedReader? I think I might know what’s wrong in here…

[ERROR rustpython_vm::object::core] Deref to a dropped obj!PyObjectRef of Some("rustpython_vm::stdlib::io::_io::BufferedReader")(0x56477466ae10)
thread 'main' panicked at '   0: <rustpython_vm::object::core::PyObjectRef as core::ops::deref::Deref>::deref
             at vm/src/object/core.rs:550:22
      <rustpython_vm::object::core::PyObjectRef as core::borrow::Borrow<rustpython_vm::object::core::PyObject>>::borrow
             at vm/src/object/core.rs:895:9
      rustpython_vm::object::ext::AsObject::as_object
             at vm/src/object/ext.rs:266:9
      rustpython_vm::object::ext::AsObject::class
             at vm/src/object/ext.rs:284:9
      rustpython_vm::vm::method::PyMethod::get
             at vm/src/vm/method.rs:23:19
   1: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::call_method
             at vm/src/vm/vm_object.rs:127:9
   2: <rustpython_vm::stdlib::io::_io::_IOBase as rustpython_vm::types::slot::Destructor>::slot_del
             at vm/src/stdlib/io.rs:542:21
   3: rustpython_vm::object::core::PyObject::drop_slow_inner::call_slot_del::{{closure}}
             at vm/src/object/core.rs:831:33
   4: rustpython_vm::vm::thread::with_vm::{{closure}}
             at vm/src/vm/thread.rs:38:14
   5: std::thread::local::LocalKey<T>::try_with
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:445:16
   6: std::thread::local::LocalKey<T>::with
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:421:9
   7: rustpython_vm::vm::thread::with_vm
             at vm/src/vm/thread.rs:27:5
   8: rustpython_vm::object::core::PyObject::drop_slow_inner::call_slot_del
             at vm/src/object/core.rs:829:23
   9: rustpython_vm::object::core::PyObject::drop_slow_inner
             at vm/src/object/core.rs:852:13
      rustpython_vm::object::core::PyObject::drop_slow
             at vm/src/object/core.rs:864:26
  10: <rustpython_vm::object::core::PyObjectRef as core::ops::drop::Drop>::drop
             at vm/src/object/core.rs:940:22
  11: core::ptr::drop_in_place<rustpython_vm::object::core::PyObjectRef>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  12: core::ptr::drop_in_place<core::option::Option<rustpython_vm::object::core::PyObjectRef>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  13: core::ptr::drop_in_place<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  14: core::ptr::drop_in_place<alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  15: core::ptr::drop_in_place<core::cell::UnsafeCell<alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  16: core::ptr::drop_in_place<lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex,alloc::boxed::Box<[core::option::Option<rustpython_vm::object::core::PyObjectRef>]>>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  17: core::ptr::drop_in_place<rustpython_vm::frame::Frame>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  18: core::ptr::drop_in_place<rustpython_vm::object::core::PyInner<rustpython_vm::frame::Frame>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  19: core::ptr::drop_in_place<alloc::boxed::Box<rustpython_vm::object::core::PyInner<rustpython_vm::frame::Frame>>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  20: core::mem::drop
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/mem/mod.rs:974:24
  21: rustpython_vm::object::core::drop_dealloc_obj
             at vm/src/object/core.rs:91:5
  22: rustpython_vm::object::core::PyObject::drop_slow
             at vm/src/object/core.rs:870:9
  23: <rustpython_vm::object::core::PyRef<T> as core::ops::drop::Drop>::drop
             at vm/src/object/core.rs:1074:22
  24: core::ptr::drop_in_place<rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  25: core::ptr::drop_in_place<core::option::Option<rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ptr/mod.rs:486:1
  26: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:393:9
  27: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
  28: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
  29: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
  30: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
  31: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  32: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  33: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      <rustpython_vm::builtins::function::PyBoundMethod as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:485:9
  34: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  35: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  36: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::vm::method::PyMethod::invoke
             at vm/src/vm/method.rs:121:9
  37: rustpython_vm::frame::ExecutingFrame::execute_method_call
             at vm/src/frame.rs:1365:21
  38: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:971:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
  39: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
  40: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
  41: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
  42: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
  43: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
  44: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
  45: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
  46: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
  47: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  48: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  49: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      <rustpython_vm::builtins::function::PyBoundMethod as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:485:9
  50: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  51: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  52: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::vm::method::PyMethod::invoke
             at vm/src/vm/method.rs:121:9
  53: rustpython_vm::frame::ExecutingFrame::execute_method_call
             at vm/src/frame.rs:1365:21
  54: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:971:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
  55: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
  56: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
  57: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
  58: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
  59: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
  60: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
  61: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
  62: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
  63: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  64: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  65: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      <rustpython_vm::builtins::function::PyBoundMethod as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:485:9
  66: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  67: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  68: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::vm::method::PyMethod::invoke
             at vm/src/vm/method.rs:121:9
  69: rustpython_vm::frame::ExecutingFrame::execute_method_call
             at vm/src/frame.rs:1365:21
  70: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:971:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
  71: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
  72: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
  73: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
  74: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
  75: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
  76: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
  77: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
  78: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
  79: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  80: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  81: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::frame::ExecutingFrame::execute_call
             at vm/src/frame.rs:1349:21
  82: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:944:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
  83: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
  84: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
  85: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
  86: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
  87: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
  88: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
  89: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
  90: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
  91: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
  92: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
  93: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::frame::ExecutingFrame::execute_call
             at vm/src/frame.rs:1349:21
  94: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:944:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
  95: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
  96: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
  97: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
  98: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
  99: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
 100: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
 101: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
 102: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
 103: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
 104: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
 105: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::frame::ExecutingFrame::execute_call
             at vm/src/frame.rs:1349:21
 106: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:944:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
 107: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
 108: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
 109: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
 110: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
 111: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
 112: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
 113: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
 114: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
 115: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
 116: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
 117: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::frame::ExecutingFrame::execute_call
             at vm/src/frame.rs:1349:21
 118: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at vm/src/frame.rs:944:17
      rustpython_vm::frame::ExecutingFrame::run
             at vm/src/frame.rs:357:26
 119: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run::{{closure}}
             at vm/src/frame.rs:229:35
 120: rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::with_exec
             at vm/src/frame.rs:186:9
      rustpython_vm::frame::<impl rustpython_vm::object::core::PyRef<rustpython_vm::frame::Frame>>::run
             at vm/src/frame.rs:229:9
 121: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at vm/src/vm/mod.rs:361:42
 122: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at vm/src/vm/mod.rs:389:26
 123: rustpython_vm::vm::VirtualMachine::with_recursion
             at vm/src/vm/mod.rs:377:22
 124: rustpython_vm::vm::VirtualMachine::with_frame
             at vm/src/vm/mod.rs:387:9
 125: rustpython_vm::vm::VirtualMachine::run_frame
             at vm/src/vm/mod.rs:361:15
      rustpython_vm::builtins::function::PyFunction::invoke_with_locals
             at vm/src/builtins/function.rs:328:31
 126: rustpython_vm::builtins::function::PyFunction::invoke
             at vm/src/builtins/function.rs:334:9
      <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/function.rs:461:9
 127: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
 128: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
 129: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::stdlib::builtins::builtins::__import__
             at vm/src/stdlib/builtins.rs:816:9
 130: core::ops::function::Fn::call
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:77:5
 131: rustpython_vm::function::builtin::<impl rustpython_vm::function::builtin::sealed::PyNativeFuncInternal<(rustpython_vm::function::builtin::OwnedParam<T1>,),R,rustpython_vm::vm::VirtualMachine> for F>::call_
             at vm/src/function/builtin.rs:79:17
 132: <F as rustpython_vm::function::builtin::IntoPyNativeFunc<(T,R,VM)>>::call
             at vm/src/function/builtin.rs:47:9
      rustpython_vm::function::builtin::IntoPyNativeFunc::into_func::{{closure}}
             at vm/src/function/builtin.rs:35:51
 133: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc/src/boxed.rs:1886:9
 134: <rustpython_vm::builtins::builtinfunc::PyBuiltinFunction as rustpython_vm::types::slot::Callable>::call
             at vm/src/builtins/builtinfunc.rs:113:9
 135: rustpython_vm::types::slot::Callable::slot_call
             at vm/src/types/slot.rs:563:13
 136: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::_invoke
             at vm/src/vm/vm_object.rs:176:30
 137: rustpython_vm::vm::vm_object::<impl rustpython_vm::vm::VirtualMachine>::invoke
             at vm/src/vm/vm_object.rs:189:9
      rustpython_vm::vm::VirtualMachine::_import_inner
             at vm/src/vm/mod.rs:515:17
 138: rustpython_vm::vm::VirtualMachine::import
             at vm/src/vm/mod.rs:464:9
 139: rustpython_vm::import::init_importlib_package::{{closure}}::{{closure}}
             at vm/src/import.rs:61:29
 140: rustpython_vm::import::init_importlib_package::{{closure}}
             at vm/src/import.rs:60:29
 141: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panic/unwind_safe.rs:271:9
 142: std::panicking::try::do_call
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:492:40
 143: __rust_try
 144: std::panicking::try
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:456:19
 145: std::panic::catch_unwind
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panic.rs:137:14
 146: rustpython_vm::vm::thread::enter_vm::{{closure}}
             at vm/src/vm/thread.rs:12:19
 147: std::thread::local::LocalKey<T>::try_with
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:445:16
 148: std::thread::local::LocalKey<T>::with
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/thread/local.rs:421:9
 149: rustpython_vm::vm::thread::enter_vm
             at vm/src/vm/thread.rs:10:5
 150: rustpython_vm::import::init_importlib_package
             at vm/src/import.rs:38:5
 151: rustpython_vm::vm::VirtualMachine::initialize
             at vm/src/vm/mod.rs:286:29
 152: rustpython_vm::vm::interpreter::Interpreter::with_init
             at vm/src/vm/interpreter.rs:51:9
 153: rustpython::interpreter::InterpreterConfig::interpreter
             at src/interpreter.rs:17:9
 154: rustpython::run
             at src/lib.rs:83:18
 155: rustpython::main
             at src/main.rs:2:5
 156: core::ops::function::FnOnce::call_once
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:248:5
 157: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/sys_common/backtrace.rs:122:18
 158: std::rt::lang_start::{{closure}}
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/rt.rs:145:18
 159: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:280:13
      std::panicking::try::do_call
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:492:40
      std::panicking::try
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:456:19
      std::panic::catch_unwind
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panic.rs:137:14
      std::rt::lang_start_internal::{{closure}}
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/rt.rs:128:48
      std::panicking::try::do_call
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:492:40
      std::panicking::try
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:456:19
      std::panic::catch_unwind
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panic.rs:137:14
      std::rt::lang_start_internal
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/rt.rs:128:20
 160: std::rt::lang_start
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/rt.rs:144:17
 161: main
 162: __libc_start_main
 163: _start

It seems https://github.com/RustPython/RustPython/blob/426f9f6359dc5f8bef914693785dc16d345fa66b/vm/src/stdlib/io.rs#L675 this line might cause missing ref count, if: the struct being copied contains fields that’s PyObjectRef/PyRef then the recorded ref count would be smaller than real ref count by one. This line was written two years ago, when our ref count system haven’t being built, gonna experiment a little more with those lines to confirm if this guess is right? @youknowone Edited: to fix that, might need to Trace every PyObjectRef/PyRef a data type own, and call clone for them, then ManuallyDrop & forgot them? Edited1: still bugged on double drop BufferedReader even after manually clone and inc ref count for PyBuffer Edited2: found out seems only PyBytes use this copy_from_slice and it doesn’t own PyObjectRef/PyRef

Sure, that will be helpful prevent it. I guess we can check similar bug with miri, but running miri is not easy as running debug mode.

cc @coolreader18

check.patch.txt I apply this patch to the earliest commit that core.rs exist, and still found this bug, I think this trace back long way ago


Commit: e76d79e725ae721920489d401fe484acb2db8800
Parents: 39e3f8faff6906166006499b398e0c7f2e377d9f
Author: Jeong Yunwon <jeong@youknowone.org>
Author Date: Thu May 12 2022 03:35:50 GMT+0800
Committer: Jeong Yunwon <jeong@youknowone.org>
Committer Date: Thu May 12 2022 03:39:07 GMT+0800
 

call_slot_del is cold