mirror of
https://github.com/python/cpython.git
synced 2025-09-01 06:28:36 +00:00
Issue #13645: pyc files now contain the size of the corresponding source
code, to avoid timestamp collisions (especially on filesystems with a low timestamp resolution) when checking for freshness of the bytecode.
This commit is contained in:
parent
1f918c1480
commit
5136ac0ca2
14 changed files with 167 additions and 49 deletions
|
@ -2800,7 +2800,7 @@ ast2obj_expr(void* _o)
|
|||
if (!result) goto failed;
|
||||
value = ast2obj_int(o->v.Yield.is_from);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "is_from", value) == -1)
|
||||
if (_PyObject_SetAttrId(result, &PyId_is_from, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->v.Yield.value);
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef unsigned short mode_t;
|
|||
Python 3.2a2 3180 (add DELETE_DEREF)
|
||||
Python 3.3a0 3190 __class__ super closure changed
|
||||
Python 3.3a0 3200 (__qualname__ added)
|
||||
3210 (added size modulo 2**32 to the pyc header)
|
||||
*/
|
||||
|
||||
/* MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||
|
@ -116,7 +117,7 @@ typedef unsigned short mode_t;
|
|||
#define STRIFY(name) QUOTE(name)
|
||||
#define MAJOR STRIFY(PY_MAJOR_VERSION)
|
||||
#define MINOR STRIFY(PY_MINOR_VERSION)
|
||||
#define MAGIC (3200 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||
#define MAGIC (3210 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||
#define TAG "cpython-" MAJOR MINOR;
|
||||
#define CACHEDIR "__pycache__"
|
||||
/* Current magic word and string tag as globals. */
|
||||
|
@ -1071,11 +1072,12 @@ make_source_pathname(PyObject *path)
|
|||
Doesn't set an exception. */
|
||||
|
||||
static FILE *
|
||||
check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname)
|
||||
check_compiled_module(PyObject *pathname, struct stat *srcstat, PyObject *cpathname)
|
||||
{
|
||||
FILE *fp;
|
||||
long magic;
|
||||
long pyc_mtime;
|
||||
long pyc_size;
|
||||
|
||||
fp = _Py_fopen(cpathname, "rb");
|
||||
if (fp == NULL)
|
||||
|
@ -1088,12 +1090,19 @@ check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname)
|
|||
return NULL;
|
||||
}
|
||||
pyc_mtime = PyMarshal_ReadLongFromFile(fp);
|
||||
if (pyc_mtime != mtime) {
|
||||
if (pyc_mtime != srcstat->st_mtime) {
|
||||
if (Py_VerboseFlag)
|
||||
PySys_FormatStderr("# %R has bad mtime\n", cpathname);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
pyc_size = PyMarshal_ReadLongFromFile(fp);
|
||||
if (pyc_size != (srcstat->st_size & 0xFFFFFFFF)) {
|
||||
if (Py_VerboseFlag)
|
||||
PySys_FormatStderr("# %R has bad size\n", cpathname);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
if (Py_VerboseFlag)
|
||||
PySys_FormatStderr("# %R matches %R\n", cpathname, pathname);
|
||||
return fp;
|
||||
|
@ -1136,6 +1145,8 @@ load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp)
|
|||
"Bad magic number in %R", cpathname);
|
||||
return NULL;
|
||||
}
|
||||
/* Skip mtime and size */
|
||||
(void) PyMarshal_ReadLongFromFile(fp);
|
||||
(void) PyMarshal_ReadLongFromFile(fp);
|
||||
co = read_compiled_module(cpathname, fp);
|
||||
if (co == NULL)
|
||||
|
@ -1196,6 +1207,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname,
|
|||
Py_UCS4 *cpathname_ucs4;
|
||||
FILE *fp;
|
||||
time_t mtime = srcstat->st_mtime;
|
||||
long size = srcstat->st_size & 0xFFFFFFFF;
|
||||
PyObject *cpathname_tmp;
|
||||
#ifdef MS_WINDOWS /* since Windows uses different permissions */
|
||||
mode_t mode = srcstat->st_mode & ~S_IEXEC;
|
||||
|
@ -1326,14 +1338,16 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname,
|
|||
return;
|
||||
}
|
||||
PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
|
||||
/* First write a 0 for mtime */
|
||||
/* First write a 0 for mtime and size */
|
||||
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
|
||||
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
|
||||
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
|
||||
fflush(fp);
|
||||
/* Now write the true mtime */
|
||||
/* Now write the true mtime and size */
|
||||
fseek(fp, 4L, 0);
|
||||
assert(mtime < LONG_MAX);
|
||||
PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION);
|
||||
PyMarshal_WriteLongToFile(size, fp, Py_MARSHAL_VERSION);
|
||||
if (fflush(fp) != 0 || ferror(fp)) {
|
||||
if (Py_VerboseFlag)
|
||||
PySys_FormatStderr("# can't write %R\n", cpathname);
|
||||
|
@ -1478,7 +1492,7 @@ load_source_module(PyObject *name, PyObject *pathname, FILE *fp)
|
|||
cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag);
|
||||
|
||||
if (cpathname != NULL)
|
||||
fpc = check_compiled_module(pathname, st.st_mtime, cpathname);
|
||||
fpc = check_compiled_module(pathname, &st, cpathname);
|
||||
else
|
||||
fpc = NULL;
|
||||
|
||||
|
|
|
@ -1844,6 +1844,8 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
|
|||
"Bad magic number in .pyc file");
|
||||
return NULL;
|
||||
}
|
||||
/* Skip mtime and size */
|
||||
(void) PyMarshal_ReadLongFromFile(fp);
|
||||
(void) PyMarshal_ReadLongFromFile(fp);
|
||||
v = PyMarshal_ReadLastObjectFromFile(fp);
|
||||
fclose(fp);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue