Skip to content

Commit

Permalink
python2: backport fix for pyc race condition, part 2
Browse files Browse the repository at this point in the history
Turns out fixing this only in importlib is not sufficient and we
need to backport CPython part of the fix too.

This patch is based on https://hg.python.org/cpython/rev/c16063765d3a
but because the code around is different there are some changes (C-strings
instead of Python objects etc.)

With this patch Tensorflow builds successfully on many-core machine.
  • Loading branch information
abbradar authored and FRidh committed Jul 17, 2019
1 parent 9a6bd59 commit da295a1
Showing 1 changed file with 76 additions and 1 deletion.
@@ -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):
Expand Down Expand Up @@ -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);

0 comments on commit da295a1

Please sign in to comment.