@@ -47,33 +47,51 @@ _Py_stackref_get_object(_PyStackRef ref)
4747 if (ref .index >= interp -> next_stackref ) {
4848 _Py_FatalErrorFormat (__func__ , "Garbled stack ref with ID %" PRIu64 "\n" , ref .index );
4949 }
50- TableEntry * entry = _Py_hashtable_get (interp -> stackref_debug_table , (void * )ref .index );
50+ TableEntry * entry = _Py_hashtable_get (interp -> open_stackrefs_table , (void * )ref .index );
5151 if (entry == NULL ) {
5252 _Py_FatalErrorFormat (__func__ , "Accessing closed stack ref with ID %" PRIu64 "\n" , ref .index );
5353 }
5454 return entry -> obj ;
5555}
5656
5757PyObject *
58- _Py_stackref_close (_PyStackRef ref )
58+ _Py_stackref_close (_PyStackRef ref , const char * filename , int linenumber )
5959{
6060 PyInterpreterState * interp = PyInterpreterState_Get ();
6161 if (ref .index >= interp -> next_stackref ) {
62- _Py_FatalErrorFormat (__func__ , "Garbled stack ref with ID %" PRIu64 "\n" , ref .index );
62+ _Py_FatalErrorFormat (__func__ , "Invalid StackRef with ID %" PRIu64 " at %s:%d\n" , (void * )ref .index , filename , linenumber );
63+
6364 }
6465 PyObject * obj ;
6566 if (ref .index <= LAST_PREDEFINED_STACKREF_INDEX ) {
6667 // Pre-allocated reference to None, False or True -- Do not clear
67- TableEntry * entry = _Py_hashtable_get (interp -> stackref_debug_table , (void * )ref .index );
68+ TableEntry * entry = _Py_hashtable_get (interp -> open_stackrefs_table , (void * )ref .index );
6869 obj = entry -> obj ;
6970 }
7071 else {
71- TableEntry * entry = _Py_hashtable_steal (interp -> stackref_debug_table , (void * )ref .index );
72+ TableEntry * entry = _Py_hashtable_steal (interp -> open_stackrefs_table , (void * )ref .index );
7273 if (entry == NULL ) {
74+ #ifdef Py_STACKREF_CLOSE_DEBUG
75+ entry = _Py_hashtable_get (interp -> closed_stackrefs_table , (void * )ref .index );
76+ if (entry != NULL ) {
77+ _Py_FatalErrorFormat (__func__ ,
78+ "Double close of ref ID %" PRIu64 " at %s:%d. Referred to instance of %s at %p. Closed at %s:%d\n" ,
79+ (void * )ref .index , filename , linenumber , entry -> classname , entry -> obj , entry -> filename , entry -> linenumber );
80+ }
81+ #endif
7382 _Py_FatalErrorFormat (__func__ , "Invalid StackRef with ID %" PRIu64 "\n" , (void * )ref .index );
7483 }
7584 obj = entry -> obj ;
7685 free (entry );
86+ #ifdef Py_STACKREF_CLOSE_DEBUG
87+ TableEntry * close_entry = make_table_entry (obj , filename , linenumber );
88+ if (close_entry == NULL ) {
89+ Py_FatalError ("No memory left for stackref debug table" );
90+ }
91+ if (_Py_hashtable_set (interp -> closed_stackrefs_table , (void * )ref .index , close_entry ) < 0 ) {
92+ Py_FatalError ("No memory left for stackref debug table" );
93+ }
94+ #endif
7795 }
7896 return obj ;
7997}
@@ -90,7 +108,7 @@ _Py_stackref_create(PyObject *obj, const char *filename, int linenumber)
90108 if (entry == NULL ) {
91109 Py_FatalError ("No memory left for stackref debug table" );
92110 }
93- if (_Py_hashtable_set (interp -> stackref_debug_table , (void * )new_id , entry ) < 0 ) {
111+ if (_Py_hashtable_set (interp -> open_stackrefs_table , (void * )new_id , entry ) < 0 ) {
94112 Py_FatalError ("No memory left for stackref debug table" );
95113 }
96114 return (_PyStackRef ){ .index = new_id };
@@ -103,9 +121,17 @@ _Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber
103121 return ;
104122 }
105123 PyInterpreterState * interp = PyInterpreterState_Get ();
106- TableEntry * entry = _Py_hashtable_get (interp -> stackref_debug_table , (void * )ref .index );
124+ TableEntry * entry = _Py_hashtable_get (interp -> open_stackrefs_table , (void * )ref .index );
107125 if (entry == NULL ) {
108- _Py_FatalErrorFormat (__func__ , "Invalid StackRef with ID %" PRIu64 "\n" , (void * )ref .index );
126+ #ifdef Py_STACKREF_CLOSE_DEBUG
127+ entry = _Py_hashtable_get (interp -> closed_stackrefs_table , (void * )ref .index );
128+ if (entry != NULL ) {
129+ _Py_FatalErrorFormat (__func__ ,
130+ "Borrow of closed ref ID %" PRIu64 " at %s:%d. Referred to instance of %s at %p. Closed at %s:%d\n" ,
131+ (void * )ref .index , filename , linenumber , entry -> classname , entry -> obj , entry -> filename , entry -> linenumber );
132+ }
133+ #endif
134+ _Py_FatalErrorFormat (__func__ , "Invalid StackRef with ID %" PRIu64 " at %s:%d\n" , (void * )ref .index , filename , linenumber );
109135 }
110136 entry -> filename_borrow = filename ;
111137 entry -> linenumber_borrow = linenumber ;
@@ -121,7 +147,7 @@ _Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef re
121147 if (entry == NULL ) {
122148 Py_FatalError ("No memory left for stackref debug table" );
123149 }
124- if (_Py_hashtable_set (interp -> stackref_debug_table , (void * )ref .index , (void * )entry ) < 0 ) {
150+ if (_Py_hashtable_set (interp -> open_stackrefs_table , (void * )ref .index , (void * )entry ) < 0 ) {
125151 Py_FatalError ("No memory left for stackref debug table" );
126152 }
127153}
147173_Py_stackref_report_leaks (PyInterpreterState * interp )
148174{
149175 int leak = 0 ;
150- _Py_hashtable_foreach (interp -> stackref_debug_table , report_leak , & leak );
176+ _Py_hashtable_foreach (interp -> open_stackrefs_table , report_leak , & leak );
151177 if (leak ) {
152178 Py_FatalError ("Stackrefs leaked." );
153179 }
0 commit comments