On Unix, use O_EXCL when creating the .pyc/.pyo files, to avoid a race condition

This commit is contained in:
Guido van Rossum 2000-09-20 20:31:38 +00:00
parent 6c0f33f8ef
commit 55a8338d7f
1 changed files with 31 additions and 1 deletions

View File

@ -28,12 +28,17 @@
#ifndef DONT_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifndef DONT_HAVE_SYS_STAT_H
#include <sys/stat.h>
#elif defined(HAVE_STAT_H)
#include <stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if defined(PYCC_VACPP)
/* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */
#define S_IFMT (S_IFDIR|S_IFCHR|S_IFREG)
@ -627,6 +632,31 @@ parse_source_module(char *pathname, FILE *fp)
}
/* Helper to open a bytecode file for writing in exclusive mode */
static FILE *
open_exclusive(char *filename)
{
#if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
/* Use O_EXCL to avoid a race condition when another process tries to
write the same file. When that happens, our open() call fails,
which is just fine (since it's only a cache).
XXX If the file exists and is writable but the directory is not
writable, the file will never be written. Oh well.
*/
int fd;
(void) unlink(filename);
fd = open(filename, O_EXCL|O_CREAT|O_WRONLY|O_TRUNC, 0666);
if (fd < 0)
return NULL;
return fdopen(fd, "wb");
#else
/* Best we can do -- on Windows this can't happen anyway */
return fopen(filename, "wb");
#endif
}
/* Write a compiled module to a file, placing the time of last
modification of its source into the header.
Errors are ignored, if a write error occurs an attempt is made to
@ -637,7 +667,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, long mtime)
{
FILE *fp;
fp = fopen(cpathname, "wb");
fp = open_exclusive(cpathname);
if (fp == NULL) {
if (Py_VerboseFlag)
PySys_WriteStderr(