[Python-checkins] python/dist/src/Python pystate.c,2.27,2.28 ceval.c,2.365,2.366

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Sat, 28 Jun 2003 14:53:54 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1:/tmp/cvs-serv29907/python

Modified Files:
	pystate.c ceval.c 
Log Message:
Add PyThreadState_SetAsyncExc(long, PyObject *).

A new API (only accessible from C) to interrupt a thread by sending it
an exception.  This is not always effective, but might help some people.
Requested by Just van Rossum and Alex Martelli.  It is intentional
that you have to write your own C extension to call it from Python.

Docs will have to wait.


Index: pystate.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pystate.c,v
retrieving revision 2.27
retrieving revision 2.28
diff -C2 -d -r2.27 -r2.28
*** pystate.c	1 May 2003 05:25:29 -0000	2.27
--- pystate.c	28 Jun 2003 21:53:52 -0000	2.28
***************
*** 144,147 ****
--- 144,149 ----
  		tstate->tick_counter = 0;
  		tstate->gilstate_counter = 0;
+ 		tstate->async_exc = NULL;
+ 		tstate->thread_id = PyThread_get_thread_ident();
  
  		tstate->dict = NULL;
***************
*** 180,183 ****
--- 182,186 ----
  
  	ZAP(tstate->dict);
+ 	ZAP(tstate->async_exc);
  
  	ZAP(tstate->curexc_type);
***************
*** 297,300 ****
--- 300,329 ----
  
  
+ /* Asynchronously raise an exception in a thread.
+    Requested by Just van Rossum and Alex Martelli.
+    To prevent naive misuse, you must write your own exception
+    to call this.  Must be called with the GIL held.
+    Returns the number of tstates modified; if it returns a number
+    greater than one, you're in trouble, and you should call it again
+    with exc=NULL to revert the effect.  This raises no exceptions. */
+ 
+ int
+ PyThreadState_SetAsyncExc(long id, PyObject *exc) {
+ 	PyThreadState *tstate = PyThreadState_Get();
+ 	PyInterpreterState *interp = tstate->interp;
+ 	PyThreadState *p;
+ 	int count = 0;
+ 	for (p = interp->tstate_head; p != NULL; p = p->next) {
+ 		if (p->thread_id != id)
+ 			continue;
+ 		ZAP(p->async_exc);
+ 		Py_XINCREF(exc);
+ 		p->async_exc = exc;
+ 		count += 1;
+ 	}
+ 	return count;
+ }
+ 
+ 
  /* Routines for advanced debuggers, requested by David Beazley.
     Don't use unless you know what you are doing! */
***************
*** 320,323 ****
--- 349,353 ----
  	return tstate->next;
  }
+ 
  
  /* Python "auto thread state" API. */

Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.365
retrieving revision 2.366
diff -C2 -d -r2.365 -r2.366
*** ceval.c	1 Jun 2003 19:21:12 -0000	2.365
--- ceval.c	28 Jun 2003 21:53:52 -0000	2.366
***************
*** 291,295 ****
  extern int _PyThread_Started; /* Flag for Py_Exit */
  
! static PyThread_type_lock interpreter_lock = 0;
  static long main_thread = 0;
  
--- 291,295 ----
  extern int _PyThread_Started; /* Flag for Py_Exit */
  
! static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */
  static long main_thread = 0;
  
***************
*** 774,777 ****
--- 774,782 ----
  
  		if (--_Py_Ticker < 0) {
+                         if (*next_instr == SETUP_FINALLY) {
+                                 /* Make the last opcode before
+                                    a try: finally: block uninterruptable. */
+                                 goto fast_next_opcode;
+                         }
  			_Py_Ticker = _Py_CheckInterval;
  			tstate->tick_counter++;
***************
*** 806,809 ****
--- 811,825 ----
  				if (PyThreadState_Swap(tstate) != NULL)
  					Py_FatalError("ceval: orphan tstate");
+ 
+ 				/* Check for thread interrupts */
+ 
+ 				if (tstate->async_exc != NULL) {
+ 					x = tstate->async_exc;
+ 					tstate->async_exc = NULL;
+ 					PyErr_SetNone(x);
+ 					Py_DECREF(x);
+ 					why = WHY_EXCEPTION;
+ 					goto on_error;
+ 				}
  			}
  #endif