Issue 16139: Python 3.3 fails when starting from read-only FS (original) (raw)

This occurs when python is installed on a read-only mount AND all the .pyc files are out-of-date. Therefore, when python starts and attempts to write a new .pyc file, _write_atomic in "Lib/importlib/_bootstrap.py" throws an OSError with an errno of EROFS, which is not handled (and ignored) and kills the interpreter.

$ python Fatal Python error: Py_Initialize: Unable to get the locale encoding Traceback (most recent call last): File "", line 1558, in _find_and_load File "", line 1525, in _find_and_load_unlocked File "", line 586, in _check_name_wrapper File "", line 1023, in load_module File "", line 1004, in load_module File "", line 562, in module_for_loader_wrapper File "", line 854, in _load_module File "", line 990, in get_code File "", line 1051, in _cache_bytecode File "", line 1074, in set_data File "", line 128, in _write_atomic OSError: [Errno 30] Read-only file system: '/lib/python3.3/encodings/pycache/init.cpython-33.pyc.139872939267056' Aborted (core dumped)

The following (hacky) patch fixes the issue for me:

--- a/Python-3.Lib/importlib/_bootstrap.py +++ b/Python-3.Lib/importlib/_bootstrap.py @@ -1070,6 +1070,10 @@ class SourceFileLoader(FileLoader, SourceLoader): # If can't get proper access, then just forget about writing # the data. return

@@ -1077,6 +1081,9 @@ class SourceFileLoader(FileLoader, SourceLoader): # Don't worry if you can't write bytecode or someone is writing # it at the same time. pass

Python 3.2 logs an error to stderr (if Python is started in verbose mode) if the directory and/or the pyc file cannot be created, and continue.

#ifdef MS_WINDOWS if (_mkdir(cpathname) < 0 && errno != EEXIST) { #else if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { #endif *dirpath = saved; if (Py_VerboseFlag) PySys_WriteStderr( "# cannot create cache dir %s\n", cpathname); return; } *dirpath = saved;

fp = open_exclusive(cpathname, mode);
if (fp == NULL) {
    if (Py_VerboseFlag)
        PySys_WriteStderr(
            "# can't create %s\n", cpathname);
    return;
}