comparison Python/pythonrun.c @ 41253:f29f1a8b7869

Patch #1680961: remove sys.exitfunc and replace it with a private C API. Also, reimplement atexit in C so it can take advantage of this private API.
author Collin Winter <collinw@gmail.com>
date Wed, 21 Mar 2007 02:57:17 +0000
parents 61fee1853ca8
children 06145fbc7ab9
comparison
equal deleted inserted replaced
41252:e12c504e466b 41253:f29f1a8b7869
54 PyCompilerFlags *, PyArena *); 54 PyCompilerFlags *, PyArena *);
55 static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, 55 static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
56 PyCompilerFlags *); 56 PyCompilerFlags *);
57 static void err_input(perrdetail *); 57 static void err_input(perrdetail *);
58 static void initsigs(void); 58 static void initsigs(void);
59 static void call_sys_exitfunc(void); 59 static void call_py_exitfuncs(void);
60 static void call_ll_exitfuncs(void); 60 static void call_ll_exitfuncs(void);
61 extern void _PyUnicode_Init(void); 61 extern void _PyUnicode_Init(void);
62 extern void _PyUnicode_Fini(void); 62 extern void _PyUnicode_Fini(void);
63 extern int _PyLong_Init(void); 63 extern int _PyLong_Init(void);
64 extern void PyLong_Fini(void); 64 extern void PyLong_Fini(void);
353 * interpreter is uninitialized until after the exit funcs have run. 353 * interpreter is uninitialized until after the exit funcs have run.
354 * Note that Threading.py uses an exit func to do a join on all the 354 * Note that Threading.py uses an exit func to do a join on all the
355 * threads created thru it, so this also protects pending imports in 355 * threads created thru it, so this also protects pending imports in
356 * the threads created via Threading. 356 * the threads created via Threading.
357 */ 357 */
358 call_sys_exitfunc(); 358 call_py_exitfuncs();
359 initialized = 0; 359 initialized = 0;
360 360
361 /* Get current thread state and interpreter pointer */ 361 /* Get current thread state and interpreter pointer */
362 tstate = PyThreadState_GET(); 362 tstate = PyThreadState_GET();
363 interp = tstate->interp; 363 interp = tstate->interp;
1555 1555
1556 #ifdef WITH_THREAD 1556 #ifdef WITH_THREAD
1557 #include "pythread.h" 1557 #include "pythread.h"
1558 #endif 1558 #endif
1559 1559
1560 static void (*pyexitfunc)(void) = NULL;
1561 /* For the atexit module. */
1562 void _Py_PyAtExit(void (*func)(void))
1563 {
1564 pyexitfunc = func;
1565 }
1566
1567 static void
1568 call_py_exitfuncs(void)
1569 {
1570 if (pyexitfunc == NULL)
1571 return;
1572
1573 (*pyexitfunc)();
1574 PyErr_Clear();
1575 }
1576
1560 #define NEXITFUNCS 32 1577 #define NEXITFUNCS 32
1561 static void (*exitfuncs[NEXITFUNCS])(void); 1578 static void (*exitfuncs[NEXITFUNCS])(void);
1562 static int nexitfuncs = 0; 1579 static int nexitfuncs = 0;
1563 1580
1564 int Py_AtExit(void (*func)(void)) 1581 int Py_AtExit(void (*func)(void))
1565 { 1582 {
1566 if (nexitfuncs >= NEXITFUNCS) 1583 if (nexitfuncs >= NEXITFUNCS)
1567 return -1; 1584 return -1;
1568 exitfuncs[nexitfuncs++] = func; 1585 exitfuncs[nexitfuncs++] = func;
1569 return 0; 1586 return 0;
1570 }
1571
1572 static void
1573 call_sys_exitfunc(void)
1574 {
1575 PyObject *exitfunc = PySys_GetObject("exitfunc");
1576
1577 if (exitfunc) {
1578 PyObject *res;
1579 Py_INCREF(exitfunc);
1580 PySys_SetObject("exitfunc", (PyObject *)NULL);
1581 res = PyEval_CallObject(exitfunc, (PyObject *)NULL);
1582 if (res == NULL) {
1583 if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
1584 PySys_WriteStderr("Error in sys.exitfunc:\n");
1585 }
1586 PyErr_Print();
1587 }
1588 Py_DECREF(exitfunc);
1589 }
1590
1591 } 1587 }
1592 1588
1593 static void 1589 static void
1594 call_ll_exitfuncs(void) 1590 call_ll_exitfuncs(void)
1595 { 1591 {