diff options
Diffstat (limited to 'Python/pythonrun.c')
-rw-r--r-- | Python/pythonrun.c | 124 |
1 files changed, 80 insertions, 44 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c index bea7fe1544..0ef36bbb8c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -62,6 +62,7 @@ static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, PyCompilerFlags *); static void err_input(perrdetail *); +static void err_free(perrdetail *); static void initsigs(void); static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); @@ -70,6 +71,8 @@ extern void _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); extern int _PyLong_Init(void); extern void PyLong_Fini(void); +extern int _PyFaulthandler_Init(void); +extern void _PyFaulthandler_Fini(void); #ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); @@ -165,18 +168,25 @@ error: return NULL; } -#if defined(HAVE_LANGINFO_H) && defined(CODESET) static char* -get_codeset(void) +get_locale_encoding(void) { +#ifdef MS_WINDOWS + char codepage[100]; + PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP()); + return get_codec_name(codepage); +#elif defined(HAVE_LANGINFO_H) && defined(CODESET) char* codeset = nl_langinfo(CODESET); if (!codeset || codeset[0] == '\0') { PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty"); return NULL; } return get_codec_name(codeset); -} +#else + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; #endif +} void Py_InitializeEx(int install_sigs) @@ -289,6 +299,10 @@ Py_InitializeEx(int install_sigs) _PyImportHooks_Init(); + /* initialize the faulthandler module */ + if (_PyFaulthandler_Init()) + Py_FatalError("Py_Initialize: can't initialize faulthandler"); + /* Initialize _warnings. */ _PyWarnings_Init(); @@ -338,9 +352,10 @@ flush_std_files(void) PyObject *fout = PySys_GetObject("stdout"); PyObject *ferr = PySys_GetObject("stderr"); PyObject *tmp; + _Py_identifier(flush); if (fout != NULL && fout != Py_None) { - tmp = PyObject_CallMethod(fout, "flush", ""); + tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); if (tmp == NULL) PyErr_WriteUnraisable(fout); else @@ -348,7 +363,7 @@ flush_std_files(void) } if (ferr != NULL && ferr != Py_None) { - tmp = PyObject_CallMethod(ferr, "flush", ""); + tmp = _PyObject_CallMethodId(ferr, &PyId_flush, ""); if (tmp == NULL) PyErr_Clear(); else @@ -462,6 +477,9 @@ Py_Finalize(void) /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ _PyImport_Fini(); + /* unload faulthandler module */ + _PyFaulthandler_Fini(); + /* Debugging stuff */ #ifdef COUNT_ALLOCS dump_counts(stdout); @@ -736,24 +754,17 @@ static int initfsencoding(PyInterpreterState *interp) { PyObject *codec; -#if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset = NULL; - - if (Py_FileSystemDefaultEncoding == NULL) { - /* On Unix, set the file system encoding according to the - user's preference, if the CODESET names a well-known - Python codec, and Py_FileSystemDefaultEncoding isn't - initialized by other means. */ - codeset = get_codeset(); - if (codeset == NULL) + + if (Py_FileSystemDefaultEncoding == NULL) + { + Py_FileSystemDefaultEncoding = get_locale_encoding(); + if (Py_FileSystemDefaultEncoding == NULL) Py_FatalError("Py_Initialize: Unable to get the locale encoding"); - Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; interp->fscodec_initialized = 1; return 0; } -#endif /* the encoding is mbcs, utf-8 or ascii */ codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding); @@ -795,6 +806,9 @@ create_stdio(PyObject* io, const char* newline; PyObject *line_buffering; int buffering, isatty; + _Py_identifier(open); + _Py_identifier(isatty); + _Py_identifier(TextIOWrapper); /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper @@ -809,9 +823,9 @@ create_stdio(PyObject* io, mode = "wb"; else mode = "rb"; - buf = PyObject_CallMethod(io, "open", "isiOOOi", - fd, mode, buffering, - Py_None, Py_None, Py_None, 0); + buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi", + fd, mode, buffering, + Py_None, Py_None, Py_None, 0); if (buf == NULL) goto error; @@ -828,7 +842,7 @@ create_stdio(PyObject* io, text = PyUnicode_FromString(name); if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) goto error; - res = PyObject_CallMethod(raw, "isatty", ""); + res = _PyObject_CallMethodId(raw, &PyId_isatty, ""); if (res == NULL) goto error; isatty = PyObject_IsTrue(res); @@ -851,9 +865,9 @@ create_stdio(PyObject* io, } #endif - stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", - buf, encoding, errors, - newline, line_buffering); + stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO", + buf, encoding, errors, + newline, line_buffering); Py_CLEAR(buf); if (stream == NULL) goto error; @@ -1585,7 +1599,7 @@ print_exception(PyObject *f, PyObject *value) moduleName = PyObject_GetAttrString(type, "__module__"); if (moduleName == NULL || !PyUnicode_Check(moduleName)) { - Py_DECREF(moduleName); + Py_XDECREF(moduleName); err = PyFile_WriteString("<unknown>", f); } else { @@ -1749,13 +1763,14 @@ flush_io(void) { PyObject *f, *r; PyObject *type, *value, *traceback; + _Py_identifier(flush); /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); f = PySys_GetObject("stderr"); if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); + r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) Py_DECREF(r); else @@ -1763,7 +1778,7 @@ flush_io(void) } f = PySys_GetObject("stdout"); if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); + r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) Py_DECREF(r); else @@ -1894,12 +1909,13 @@ PyParser_ASTFromString(const char *s, const char *filename, int start, flags->cf_flags |= iflags & PyCF_MASK; mod = PyAST_FromNode(n, flags, filename, arena); PyNode_Free(n); - return mod; } else { err_input(&err); - return NULL; + mod = NULL; } + err_free(&err); + return mod; } mod_ty @@ -1924,14 +1940,15 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc, flags->cf_flags |= iflags & PyCF_MASK; mod = PyAST_FromNode(n, flags, filename, arena); PyNode_Free(n); - return mod; } else { err_input(&err); if (errcode) *errcode = err.error; - return NULL; + mod = NULL; } + err_free(&err); + return mod; } /* Simplified interface to parsefile -- return node or set exception */ @@ -1945,6 +1962,7 @@ PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int fla start, NULL, NULL, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1959,6 +1977,7 @@ PyParser_SimpleParseStringFlags(const char *str, int start, int flags) start, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1971,6 +1990,7 @@ PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename, &_PyParser_Grammar, start, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1984,11 +2004,23 @@ PyParser_SimpleParseStringFilename(const char *str, const char *filename, int st even parser modules. */ void +PyParser_ClearError(perrdetail *err) +{ + err_free(err); +} + +void PyParser_SetError(perrdetail *err) { err_input(err); } +static void +err_free(perrdetail *err) +{ + Py_CLEAR(err->filename); +} + /* Set the error appropriate to the given input error code (see errcode.h) */ static void @@ -1996,7 +2028,6 @@ err_input(perrdetail *err) { PyObject *v, *w, *errtype, *errtext; PyObject *msg_obj = NULL; - PyObject *filename; char *msg = NULL; errtype = PyExc_SyntaxError; @@ -2082,17 +2113,8 @@ err_input(perrdetail *err) errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), "replace"); } - if (err->filename != NULL) - filename = PyUnicode_DecodeFSDefault(err->filename); - else { - Py_INCREF(Py_None); - filename = Py_None; - } - if (filename != NULL) - v = Py_BuildValue("(NiiN)", filename, - err->lineno, err->offset, errtext); - else - v = NULL; + v = Py_BuildValue("(OiiN)", err->filename, + err->lineno, err->offset, errtext); if (v != NULL) { if (msg_obj) w = Py_BuildValue("(OO)", msg_obj, v); @@ -2116,11 +2138,24 @@ cleanup: void Py_FatalError(const char *msg) { + const int fd = fileno(stderr); + PyThreadState *tstate; + fprintf(stderr, "Fatal Python error: %s\n", msg); fflush(stderr); /* it helps in Windows debug build */ if (PyErr_Occurred()) { PyErr_PrintEx(0); } + else { + tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current); + if (tstate != NULL) { + fputc('\n', stderr); + fflush(stderr); + _Py_DumpTracebackThreads(fd, tstate->interp, tstate); + } + _PyFaulthandler_Fini(); + } + #ifdef MS_WINDOWS { size_t len = strlen(msg); @@ -2175,6 +2210,7 @@ static void wait_for_thread_shutdown(void) { #ifdef WITH_THREAD + _Py_identifier(_shutdown); PyObject *result; PyThreadState *tstate = PyThreadState_GET(); PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, @@ -2184,7 +2220,7 @@ wait_for_thread_shutdown(void) PyErr_Clear(); return; } - result = PyObject_CallMethod(threading, "_shutdown", ""); + result = _PyObject_CallMethodId(threading, &PyId__shutdown, ""); if (result == NULL) { PyErr_WriteUnraisable(threading); } |