|
1 | 1 | use crate::{ |
2 | 2 | AsObject, PyObject, PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject, |
3 | 3 | VirtualMachine, |
4 | | - builtins::{PyStr, PyStrRef}, |
| 4 | + builtins::{PyBytes, PyStr, PyStrRef}, |
5 | 5 | common::borrow::{BorrowedValue, BorrowedValueMut}, |
6 | 6 | protocol::{BufferFlags, PyBuffer}, |
7 | 7 | }; |
@@ -55,13 +55,12 @@ impl ArgBytesLike { |
55 | 55 | /// `borrow_buf` may answer with a lock that every other thread writing to |
56 | 56 | /// the same object waits on, and a thread waiting on a lock never reaches |
57 | 57 | /// a safepoint, so keeping one across a wait for a peer, a pipe or a |
58 | | - /// signal stops the world from being stopped at all. Bytes reached that |
59 | | - /// way are copied out first. Bytes that lock nothing -- an immutable |
60 | | - /// object's -- are borrowed where they lie, which is all CPython holds in |
61 | | - /// either case. |
| 58 | + /// signal stops the world from being stopped at all. Only storage owned |
| 59 | + /// by `bytes` can be borrowed across that wait. Other exporters are copied: |
| 60 | + /// an unlocked or readonly buffer may still alias writable raw memory. |
62 | 61 | pub fn borrow_buf_unlocked(&self, vm: &VirtualMachine) -> PyResult<UnlockedBuf<'_>> { |
63 | 62 | let borrowed = self.borrow_buf(); |
64 | | - if !borrowed.is_locked() { |
| 63 | + if !borrowed.is_locked() && self.source_object().downcast_ref::<PyBytes>().is_some() { |
65 | 64 | return Ok(UnlockedBuf::Borrowed(borrowed)); |
66 | 65 | } |
67 | 66 | let mut copy = Vec::new(); |
|
0 commit comments