Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 55a8338

Browse files
committed
On Unix, use O_EXCL when creating the .pyc/.pyo files, to avoid a race condition
1 parent 6c0f33f commit 55a8338

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

Python/import.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@
2828
#ifndef DONT_HAVE_SYS_TYPES_H
2929
#include <sys/types.h>
3030
#endif
31+
3132
#ifndef DONT_HAVE_SYS_STAT_H
3233
#include <sys/stat.h>
3334
#elif defined(HAVE_STAT_H)
3435
#include <stat.h>
3536
#endif
3637

38+
#ifdef HAVE_FCNTL_H
39+
#include <fcntl.h>
40+
#endif
41+
3742
#if defined(PYCC_VACPP)
3843
/* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */
3944
#define S_IFMT (S_IFDIR|S_IFCHR|S_IFREG)
@@ -627,6 +632,31 @@ parse_source_module(char *pathname, FILE *fp)
627632
}
628633

629634

635+
/* Helper to open a bytecode file for writing in exclusive mode */
636+
637+
static FILE *
638+
open_exclusive(char *filename)
639+
{
640+
#if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
641+
/* Use O_EXCL to avoid a race condition when another process tries to
642+
write the same file. When that happens, our open() call fails,
643+
which is just fine (since it's only a cache).
644+
XXX If the file exists and is writable but the directory is not
645+
writable, the file will never be written. Oh well.
646+
*/
647+
int fd;
648+
(void) unlink(filename);
649+
fd = open(filename, O_EXCL|O_CREAT|O_WRONLY|O_TRUNC, 0666);
650+
if (fd < 0)
651+
return NULL;
652+
return fdopen(fd, "wb");
653+
#else
654+
/* Best we can do -- on Windows this can't happen anyway */
655+
return fopen(filename, "wb");
656+
#endif
657+
}
658+
659+
630660
/* Write a compiled module to a file, placing the time of last
631661
modification of its source into the header.
632662
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)
637667
{
638668
FILE *fp;
639669

640-
fp = fopen(cpathname, "wb");
670+
fp = open_exclusive(cpathname);
641671
if (fp == NULL) {
642672
if (Py_VerboseFlag)
643673
PySys_WriteStderr(

0 commit comments

Comments
 (0)