diff --git a/pkgs/development/interpreters/python/cpython/2.7/atomic_pyc.patch b/pkgs/development/interpreters/python/cpython/2.7/atomic_pyc.patch index 56c75cbdeeaf7a..06d3718d499373 100644 --- a/pkgs/development/interpreters/python/cpython/2.7/atomic_pyc.patch +++ b/pkgs/development/interpreters/python/cpython/2.7/atomic_pyc.patch @@ -1,5 +1,5 @@ diff --git a/Lib/py_compile.py b/Lib/py_compile.py -index 978da73..3559eb9 100644 +index 978da73d74..3559eb95ca 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -120,16 +120,27 @@ def compile(file, cfile=None, dfile=None, doraise=False): @@ -39,3 +39,78 @@ index 978da73..3559eb9 100644 def main(args=None): """Compile several source files. +diff --git a/Python/import.c b/Python/import.c +index 1e31d79279..f78a1efcf0 100644 +--- a/Python/import.c ++++ b/Python/import.c +@@ -951,6 +951,8 @@ static void + write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, time_t mtime) + { + FILE *fp; ++ size_t cpathname_len; ++ char *cpathname_tmp; + #ifdef MS_WINDOWS /* since Windows uses different permissions */ + mode_t mode = srcstat->st_mode & ~S_IEXEC; + /* Issue #6074: We ensure user write access, so we can delete it later +@@ -963,11 +965,28 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, t + mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; + #endif + ++#ifdef MS_WINDOWS + fp = open_exclusive(cpathname, mode); ++#else ++ /* Under POSIX, we first write to a tmp file and then take advantage ++ of atomic renaming. */ ++ cpathname_len = strlen(cpathname); ++ cpathname_tmp = PyMem_MALLOC(cpathname_len + 5); ++ if (cpathname_tmp == NULL) { ++ PyErr_Clear(); ++ return; ++ } ++ memcpy(cpathname_tmp, cpathname, cpathname_len); ++ memcpy(cpathname_tmp + cpathname_len, ".tmp", 5); ++ fp = open_exclusive(cpathname_tmp, mode); ++#endif + if (fp == NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "# can't create %s\n", cpathname); ++#ifndef MS_WINDOWS ++ PyMem_FREE(cpathname_tmp); ++#endif + return; + } + PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); +@@ -979,7 +998,12 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, t + PySys_WriteStderr("# can't write %s\n", cpathname); + /* Don't keep partial file */ + fclose(fp); ++#ifdef MS_WINDOWS + (void) unlink(cpathname); ++#else ++ (void) unlink(cpathname_tmp); ++ PyMem_FREE(cpathname_tmp); ++#endif + return; + } + /* Now write the true mtime (as a 32-bit field) */ +@@ -989,6 +1013,19 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, t + PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); + fflush(fp); + } ++ /* Under POSIX, do an atomic rename */ ++#ifndef MS_WINDOWS ++ if (rename(cpathname_tmp, cpathname)) { ++ if (Py_VerboseFlag) ++ PySys_WriteStderr("# can't write %s\n", cpathname); ++ /* Don't keep tmp file */ ++ fclose(fp); ++ (void) unlink(cpathname_tmp); ++ PyMem_FREE(cpathname_tmp); ++ return; ++ } ++ PyMem_FREE(cpathname_tmp); ++#endif + fclose(fp); + if (Py_VerboseFlag) + PySys_WriteStderr("# wrote %s\n", cpathname);