mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	After approval from Anthony, merge the tim-current_frames
branch into the trunk. This adds a new sys._current_frames() function, which returns a dict mapping thread id to topmost thread stack frame.
This commit is contained in:
		
							parent
							
								
									2b221ed657
								
							
						
					
					
						commit
						32a8361f2d
					
				
					 6 changed files with 166 additions and 11 deletions
				
			
		|  | @ -444,15 +444,15 @@ _PyGILState_NoteThreadState(PyThreadState* tstate) | |||
| 	/* If autoTLSkey is 0, this must be the very first threadstate created
 | ||||
| 	   in Py_Initialize().  Don't do anything for now (we'll be back here | ||||
| 	   when _PyGILState_Init is called). */ | ||||
| 	if (!autoTLSkey)  | ||||
| 	if (!autoTLSkey) | ||||
| 		return; | ||||
| 	 | ||||
| 
 | ||||
| 	/* Stick the thread state for this thread in thread local storage.
 | ||||
| 
 | ||||
| 	   The only situation where you can legitimately have more than one | ||||
| 	   thread state for an OS level thread is when there are multiple | ||||
| 	   interpreters, when: | ||||
| 	        | ||||
| 
 | ||||
| 	       a) You shouldn't really be using the PyGILState_ APIs anyway, | ||||
| 	          and: | ||||
| 
 | ||||
|  | @ -550,6 +550,54 @@ PyGILState_Release(PyGILState_STATE oldstate) | |||
| 		PyEval_SaveThread(); | ||||
| } | ||||
| 
 | ||||
| /* The implementation of sys._current_frames().  This is intended to be
 | ||||
|    called with the GIL held, as it will be when called via | ||||
|    sys._current_frames().  It's possible it would work fine even without | ||||
|    the GIL held, but haven't thought enough about that. | ||||
| */ | ||||
| PyObject * | ||||
| _PyThread_CurrentFrames(void) | ||||
| { | ||||
| 	PyObject *result; | ||||
| 	PyInterpreterState *i; | ||||
| 
 | ||||
| 	result = PyDict_New(); | ||||
| 	if (result == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	/* for i in all interpreters:
 | ||||
| 	 *     for t in all of i's thread states: | ||||
| 	 *          if t's frame isn't NULL, map t's id to its frame | ||||
| 	 * Because these lists can mutute even when the GIL is held, we | ||||
| 	 * need to grab head_mutex for the duration. | ||||
| 	 */ | ||||
| 	HEAD_LOCK(); | ||||
| 	for (i = interp_head; i != NULL; i = i->next) { | ||||
| 		PyThreadState *t; | ||||
| 		for (t = i->tstate_head; t != NULL; t = t->next) { | ||||
| 			PyObject *id; | ||||
| 			int stat; | ||||
| 			struct _frame *frame = t->frame; | ||||
| 			if (frame == NULL) | ||||
| 				continue; | ||||
| 			id = PyInt_FromLong(t->thread_id); | ||||
| 			if (id == NULL) | ||||
| 				goto Fail; | ||||
| 			stat = PyDict_SetItem(result, id, (PyObject *)frame); | ||||
| 			Py_DECREF(id); | ||||
| 			if (stat < 0) | ||||
| 				goto Fail; | ||||
| 		} | ||||
| 	} | ||||
| 	HEAD_UNLOCK(); | ||||
| 	return result; | ||||
| 
 | ||||
|  Fail: | ||||
|  	HEAD_UNLOCK(); | ||||
|  	Py_DECREF(result); | ||||
|  	return NULL; | ||||
| } | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Peters
						Tim Peters