Issue #10914: Initialize correctly the filesystem codec when creating a new

subinterpreter to fix a bootstrap issue with codecs implemented in Python, as
the ISO-8859-15 codec.

Add fscodec_initialized attribute to the PyInterpreterState structure.
This commit is contained in:
Victor Stinner 2011-04-27 00:24:21 +02:00
parent 1188935af9
commit 3cbf14bfb1
5 changed files with 43 additions and 15 deletions

View File

@ -31,6 +31,7 @@ typedef struct _is {
PyObject *codec_search_cache; PyObject *codec_search_cache;
PyObject *codec_error_registry; PyObject *codec_error_registry;
int codecs_initialized; int codecs_initialized;
int fscodec_initialized;
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
int dlopenflags; int dlopenflags;

View File

@ -10,6 +10,10 @@ What's New in Python 3.2.1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #10914: Initialize correctly the filesystem codec when creating a new
subinterpreter to fix a bootstrap issue with codecs implemented in Python, as
the ISO-8859-15 codec.
- Issue #10517: After fork(), reinitialize the TLS used by the PyGILState_* - Issue #10517: After fork(), reinitialize the TLS used by the PyGILState_*
APIs, to avoid a crash with the pthread implementation in RHEL 5. Patch APIs, to avoid a crash with the pthread implementation in RHEL 5. Patch
by Charles-François Natali. by Charles-François Natali.

View File

@ -1626,7 +1626,17 @@ PyUnicode_EncodeFSDefault(PyObject *unicode)
PyUnicode_GET_SIZE(unicode), PyUnicode_GET_SIZE(unicode),
"surrogateescape"); "surrogateescape");
#else #else
if (Py_FileSystemDefaultEncoding) { PyInterpreterState *interp = PyThreadState_GET()->interp;
/* Bootstrap check: if the filesystem codec is implemented in Python, we
cannot use it to encode and decode filenames before it is loaded. Load
the Python codec requires to encode at least its own filename. Use the C
version of the locale codec until the codec registry is initialized and
the Python codec is loaded.
Py_FileSystemDefaultEncoding is shared between all interpreters, we
cannot only rely on it: check also interp->fscodec_initialized for
subinterpreters. */
if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) {
return PyUnicode_AsEncodedString(unicode, return PyUnicode_AsEncodedString(unicode,
Py_FileSystemDefaultEncoding, Py_FileSystemDefaultEncoding,
"surrogateescape"); "surrogateescape");
@ -1818,12 +1828,17 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
#elif defined(__APPLE__) #elif defined(__APPLE__)
return PyUnicode_DecodeUTF8(s, size, "surrogateescape"); return PyUnicode_DecodeUTF8(s, size, "surrogateescape");
#else #else
/* During the early bootstrapping process, Py_FileSystemDefaultEncoding PyInterpreterState *interp = PyThreadState_GET()->interp;
can be undefined. If it is case, decode using UTF-8. The following assumes /* Bootstrap check: if the filesystem codec is implemented in Python, we
that Py_FileSystemDefaultEncoding is set to a built-in encoding during the cannot use it to encode and decode filenames before it is loaded. Load
bootstrapping process where the codecs aren't ready yet. the Python codec requires to encode at least its own filename. Use the C
*/ version of the locale codec until the codec registry is initialized and
if (Py_FileSystemDefaultEncoding) { the Python codec is loaded.
Py_FileSystemDefaultEncoding is shared between all interpreters, we
cannot only rely on it: check also interp->fscodec_initialized for
subinterpreters. */
if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) {
return PyUnicode_Decode(s, size, return PyUnicode_Decode(s, size,
Py_FileSystemDefaultEncoding, Py_FileSystemDefaultEncoding,
"surrogateescape"); "surrogateescape");

View File

@ -79,6 +79,7 @@ PyInterpreterState_New(void)
interp->codec_search_cache = NULL; interp->codec_search_cache = NULL;
interp->codec_error_registry = NULL; interp->codec_error_registry = NULL;
interp->codecs_initialized = 0; interp->codecs_initialized = 0;
interp->fscodec_initialized = 0;
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
#ifdef RTLD_NOW #ifdef RTLD_NOW
interp->dlopenflags = RTLD_NOW; interp->dlopenflags = RTLD_NOW;

View File

@ -53,7 +53,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */
/* Forward */ /* Forward */
static void initmain(void); static void initmain(void);
static void initfsencoding(void); static int initfsencoding(PyInterpreterState *interp);
static void initsite(void); static void initsite(void);
static int initstdio(void); static int initstdio(void);
static void flush_io(void); static void flush_io(void);
@ -291,7 +291,8 @@ Py_InitializeEx(int install_sigs)
_PyTime_Init(); _PyTime_Init();
initfsencoding(); if (initfsencoding(interp) < 0)
Py_FatalError("Py_Initialize: unable to load the file system codec");
if (install_sigs) if (install_sigs)
initsigs(); /* Signal handling stuff, including initintr() */ initsigs(); /* Signal handling stuff, including initintr() */
@ -608,6 +609,10 @@ Py_NewInterpreter(void)
Py_DECREF(pstderr); Py_DECREF(pstderr);
_PyImportHooks_Init(); _PyImportHooks_Init();
if (initfsencoding(interp) < 0)
goto handle_error;
if (initstdio() < 0) if (initstdio() < 0)
Py_FatalError( Py_FatalError(
"Py_Initialize: can't initialize sys standard streams"); "Py_Initialize: can't initialize sys standard streams");
@ -720,8 +725,8 @@ initmain(void)
} }
} }
static void static int
initfsencoding(void) initfsencoding(PyInterpreterState *interp)
{ {
PyObject *codec; PyObject *codec;
#if defined(HAVE_LANGINFO_H) && defined(CODESET) #if defined(HAVE_LANGINFO_H) && defined(CODESET)
@ -738,7 +743,8 @@ initfsencoding(void)
Py_FileSystemDefaultEncoding = codeset; Py_FileSystemDefaultEncoding = codeset;
Py_HasFileSystemDefaultEncoding = 0; Py_HasFileSystemDefaultEncoding = 0;
return; interp->fscodec_initialized = 1;
return 0;
} }
#endif #endif
@ -748,10 +754,11 @@ initfsencoding(void)
/* Such error can only occurs in critical situations: no more /* Such error can only occurs in critical situations: no more
* memory, import a module of the standard library failed, * memory, import a module of the standard library failed,
* etc. */ * etc. */
Py_FatalError("Py_Initialize: unable to load the file system codec"); return -1;
} else {
Py_DECREF(codec);
} }
Py_DECREF(codec);
interp->fscodec_initialized = 1;
return 0;
} }
/* Import the site module (not into __main__ though) */ /* Import the site module (not into __main__ though) */