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