File tree Expand file tree Collapse file tree 2 files changed +22
-4
lines changed
Expand file tree Collapse file tree 2 files changed +22
-4
lines changed Original file line number Diff line number Diff line change @@ -99,7 +99,7 @@ impl RefCount {
9999 #[ inline]
100100 pub fn inc ( & self ) {
101101 let val = State :: from_raw ( self . state . fetch_add ( COUNT , Ordering :: SeqCst ) ) ;
102- if val. destructed ( ) {
102+ if val. destructed ( ) || ( val . strong ( ) as usize ) > STRONG - 1 {
103103 refcount_overflow ( ) ;
104104 }
105105 if val. strong ( ) == 0 {
@@ -211,8 +211,9 @@ impl Drop for DeferredDropGuard {
211211 IN_DEFERRED_CONTEXT . with ( |in_ctx| {
212212 in_ctx. set ( self . was_in_context ) ;
213213 } ) ;
214- // Only flush if we're the outermost context
215- if !self . was_in_context {
214+ // Only flush if we're the outermost context and not already panicking
215+ // (flushing during unwinding risks double-panic → process abort).
216+ if !self . was_in_context && !std:: thread:: panicking ( ) {
216217 flush_deferred_drops ( ) ;
217218 }
218219 }
Original file line number Diff line number Diff line change @@ -127,7 +127,9 @@ mod trashcan {
127127 #[ inline]
128128 pub ( super ) unsafe fn end ( ) {
129129 let depth = DEALLOC_DEPTH . with ( |d| {
130- let depth = d. get ( ) - 1 ;
130+ let depth = d. get ( ) ;
131+ debug_assert ! ( depth > 0 , "trashcan::end called without matching begin" ) ;
132+ let depth = depth - 1 ;
131133 d. set ( depth) ;
132134 depth
133135 } ) ;
@@ -434,6 +436,21 @@ impl WeakRefList {
434436 // Re-acquire lock for linked list insertion
435437 let _lock = weakref_lock:: lock ( obj as * const PyObject as usize ) ;
436438
439+ // Re-check: another thread may have inserted a generic ref while we
440+ // were allocating outside the lock. If so, reuse it and drop ours.
441+ if is_generic {
442+ let generic_ptr = self . generic . load ( Ordering :: Relaxed ) ;
443+ if !generic_ptr. is_null ( ) {
444+ let generic = unsafe { & * generic_ptr } ;
445+ if generic. 0 . ref_count . safe_inc ( ) {
446+ // Nullify wr_object so drop_inner won't unlink an
447+ // uninserted node (which would corrupt the list head).
448+ weak. wr_object . store ( ptr:: null_mut ( ) , Ordering :: Relaxed ) ;
449+ return unsafe { PyRef :: from_raw ( generic_ptr) } ;
450+ }
451+ }
452+ }
453+
437454 // Insert into linked list under stripe lock
438455 let node_ptr = NonNull :: from ( & * weak) ;
439456 unsafe {
You can’t perform that action at this time.
0 commit comments