diff -r 0f5eb87afd23 Include/Python.h --- a/Include/Python.h Fri Apr 15 02:14:19 2016 +0000 +++ b/Include/Python.h Fri Apr 15 14:51:10 2016 +0200 @@ -139,6 +139,7 @@ #include "pystrtod.h" #include "pystrcmp.h" #include "dtoa.h" +#include "fileutils.h" /* _Py_Mangle is defined in compile.c */ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); diff -r 0f5eb87afd23 Include/fileutils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/fileutils.h Fri Apr 15 14:51:10 2016 +0200 @@ -0,0 +1,19 @@ +#ifndef Py_FILEUTILS_H +#define Py_FILEUTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Try to make the file descriptor non-inheritable. Ignore errors. */ +PyAPI_FUNC(void) _Py_try_set_non_inheritable(int fd); + +/* Wrapper to fopen() which tries to make the file non-inheritable on success. + Ignore errors on trying to set the file descriptor non-inheritable. */ +PyAPI_FUNC(FILE*) _Py_fopen(const char *path, const char *mode); + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_FILEUTILS_H */ diff -r 0f5eb87afd23 Makefile.pre.in --- a/Makefile.pre.in Fri Apr 15 02:14:19 2016 +0000 +++ b/Makefile.pre.in Fri Apr 15 14:51:10 2016 +0200 @@ -312,7 +312,7 @@ ASDLGEN= $(srcdir)/Parser/asdl_c.py OPCODETARGETS_H= \ $(srcdir)/Python/opcode_targets.h - + OPCODETARGETGEN= \ $(srcdir)/Python/makeopcodetargets.py @@ -351,7 +351,7 @@ PYTHON_OBJS= \ Python/pymath.o \ Python/pystate.o \ Python/pythonrun.o \ - Python/random.o \ + Python/random.o \ Python/structmember.o \ Python/symtable.o \ Python/sysmodule.o \ @@ -362,6 +362,7 @@ PYTHON_OBJS= \ Python/dtoa.o \ Python/formatter_unicode.o \ Python/formatter_string.o \ + Python/fileutils.o \ Python/$(DYNLOADFILE) \ $(LIBOBJS) \ $(MACHDEP_OBJS) \ @@ -781,6 +782,7 @@ PYTHON_HEADERS= \ Include/errcode.h \ Include/eval.h \ Include/fileobject.h \ + Include/fileutils.h \ Include/floatobject.h \ Include/frameobject.h \ Include/funcobject.h \ diff -r 0f5eb87afd23 Modules/_bsddb.c --- a/Modules/_bsddb.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/_bsddb.c Fri Apr 15 14:51:10 2016 +0200 @@ -3436,26 +3436,25 @@ DB_verify(DBObject* self, PyObject* args FILE* outFile=NULL; static char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL }; + PyObject *error; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames, &fileName, &dbName, &outFileName, &flags)) return NULL; CHECK_DB_NOT_CLOSED(self); - if (outFileName) - outFile = fopen(outFileName, "w"); + if (outFileName) { + outFile = _Py_fopen(outFileName, "w"); /* XXX(nnorwitz): it should probably be an exception if outFile can't be opened. */ - - { /* DB.verify acts as a DB handle destructor (like close) */ - PyObject *error; - - error=DB_close_internal(self, 0, 1); - if (error) { - if (outFile) - fclose(outFile); - return error; - } + } + + /* DB.verify acts as a DB handle destructor (like close) */ + error = DB_close_internal(self, 0, 1); + if (error) { + if (outFile) + fclose(outFile); + return error; } MYDB_BEGIN_ALLOW_THREADS; diff -r 0f5eb87afd23 Modules/_hotshot.c --- a/Modules/_hotshot.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/_hotshot.c Fri Apr 15 14:51:10 2016 +0200 @@ -1525,6 +1525,7 @@ hotshot_profiler(PyObject *unused, PyObj PyErr_SetFromErrnoWithFilename(PyExc_IOError, logfilename); return NULL; } + if (timeofday_diff == 0) { /* Run this several times since sometimes the first * doesn't give the lowest values, and we're really trying diff -r 0f5eb87afd23 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/_testcapimodule.c Fri Apr 15 14:51:10 2016 +0200 @@ -2169,7 +2169,7 @@ pymarshal_write_long_to_file(PyObject* s &value, &filename, &version)) return NULL; - fp = fopen(filename, "wb"); + fp = _Py_fopen(filename, "wb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -2195,7 +2195,7 @@ pymarshal_write_object_to_file(PyObject* &obj, &filename, &version)) return NULL; - fp = fopen(filename, "wb"); + fp = _Py_fopen(filename, "wb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -2220,7 +2220,7 @@ pymarshal_read_short_from_file(PyObject* if (!PyArg_ParseTuple(args, "s:pymarshal_read_short_from_file", &filename)) return NULL; - fp = fopen(filename, "rb"); + fp = _Py_fopen(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -2245,7 +2245,7 @@ pymarshal_read_long_from_file(PyObject* if (!PyArg_ParseTuple(args, "s:pymarshal_read_long_from_file", &filename)) return NULL; - fp = fopen(filename, "rb"); + fp = _Py_fopen(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -2271,7 +2271,7 @@ pymarshal_read_last_object_from_file(PyO if (!PyArg_ParseTuple(args, "s:pymarshal_read_last_object_from_file", &filename)) return NULL; - fp = fopen(filename, "rb"); + fp = _Py_fopen(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -2295,7 +2295,7 @@ pymarshal_read_object_from_file(PyObject if (!PyArg_ParseTuple(args, "s:pymarshal_read_object_from_file", &filename)) return NULL; - fp = fopen(filename, "rb"); + fp = _Py_fopen(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; diff -r 0f5eb87afd23 Modules/getpath.c --- a/Modules/getpath.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/getpath.c Fri Apr 15 14:51:10 2016 +0200 @@ -341,7 +341,7 @@ search_for_exec_prefix(char *argv0_path, strcpy(exec_prefix, argv0_path); joinpath(exec_prefix, "pybuilddir.txt"); if (isfile(exec_prefix)) { - FILE *f = fopen(exec_prefix, "r"); + FILE *f = _Py_fopen(exec_prefix, "r"); if (f == NULL) errno = 0; else { diff -r 0f5eb87afd23 Modules/linuxaudiodev.c --- a/Modules/linuxaudiodev.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/linuxaudiodev.c Fri Apr 15 14:51:10 2016 +0200 @@ -120,10 +120,13 @@ newladobject(PyObject *arg) basedev = "/dev/dsp"; } - if ((fd = open(basedev, imode)) == -1) { + fd = open(basedev, imode); + if (fd == -1) { PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev); return NULL; } + _Py_try_set_non_inheritable(fd); + if (imode == O_WRONLY && ioctl(fd, SNDCTL_DSP_NONBLOCK, NULL) == -1) { PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev); return NULL; diff -r 0f5eb87afd23 Modules/main.c --- a/Modules/main.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/main.c Fri Apr 15 14:51:10 2016 +0200 @@ -148,12 +148,13 @@ static void RunStartupFile(PyCompilerFla { char *startup = Py_GETENV("PYTHONSTARTUP"); if (startup != NULL && startup[0] != '\0') { - FILE *fp = fopen(startup, "r"); + FILE *fp = _Py_fopen(startup, "r"); if (fp != NULL) { (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf); PyErr_Clear(); fclose(fp); - } else { + } + else { int save_errno; save_errno = errno; PySys_WriteStderr("Could not open PYTHONSTARTUP\n"); @@ -602,13 +603,15 @@ Py_Main(int argc, char **argv) } if (sts==-1 && filename!=NULL) { - if ((fp = fopen(filename, "r")) == NULL) { + fp = _Py_fopen(filename, "r"); + if (fp == NULL) { fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], filename, errno, strerror(errno)); return 2; } - else if (skipfirstline) { + + if (skipfirstline) { int ch; /* Push back first newline so line numbers remain the same */ diff -r 0f5eb87afd23 Modules/mmapmodule.c --- a/Modules/mmapmodule.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/mmapmodule.c Fri Apr 15 14:51:10 2016 +0200 @@ -1250,14 +1250,17 @@ new_mmap_object(PyTypeObject *type, PyOb PyErr_SetFromErrno(mmap_module_error); return NULL; } + _Py_try_set_non_inheritable(fd); #endif - } else { + } + else { m_obj->fd = dup(fd); if (m_obj->fd == -1) { Py_DECREF(m_obj); PyErr_SetFromErrno(mmap_module_error); return NULL; } + _Py_try_set_non_inheritable(fd); } m_obj->data = mmap(NULL, map_size, diff -r 0f5eb87afd23 Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/ossaudiodev.c Fri Apr 15 14:51:10 2016 +0200 @@ -115,10 +115,12 @@ newossobject(PyObject *arg) one open at a time. This does *not* affect later I/O; OSS provides a special ioctl() for non-blocking read/write, which is exposed via oss_nonblock() below. */ - if ((fd = open(devicename, imode|O_NONBLOCK)) == -1) { + fd = open(devicename, imode|O_NONBLOCK); + if (fd == -1) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename); return NULL; } + _Py_try_set_non_inheritable(fd); /* And (try to) put it back in blocking mode so we get the expected write() semantics. */ @@ -138,6 +140,7 @@ newossobject(PyObject *arg) close(fd); return NULL; } + self->devicename = devicename; self->fd = fd; self->mode = imode; @@ -177,10 +180,12 @@ newossmixerobject(PyObject *arg) devicename = "/dev/mixer"; } - if ((fd = open(devicename, O_RDWR)) == -1) { + fd = open(devicename, O_RDWR); + if (fd == -1) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename); return NULL; } + _Py_try_set_non_inheritable(fd); if ((self = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) { close(fd); diff -r 0f5eb87afd23 Modules/posixmodule.c --- a/Modules/posixmodule.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/posixmodule.c Fri Apr 15 14:51:10 2016 +0200 @@ -4855,8 +4855,7 @@ static PyObject * if (dup2(p_fd[0].rd, 0) == 0) { close(p_fd[0].rd); - i = fcntl(p_fd[0].wr, F_GETFD, 0); - fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC); + _Py_try_set_non_inheritable(p_fd[0].wr); if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL) { close(p_fd[0].wr); @@ -4874,8 +4873,7 @@ static PyObject * if (dup2(p_fd[1].wr, 1) == 1) { close(p_fd[1].wr); - i = fcntl(p_fd[1].rd, F_GETFD, 0); - fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC); + _Py_try_set_non_inheritable(p_fd[1].rd); if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL) { close(p_fd[1].rd); @@ -4897,8 +4895,7 @@ static PyObject * if (dup2(p_fd[2].wr, 2) == 2) { close(p_fd[2].wr); - i = fcntl(p_fd[2].rd, F_GETFD, 0); - fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC); + _Py_try_set_non_inheritable(p_fd[2].rd); if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL) { close(p_fd[2].rd); diff -r 0f5eb87afd23 Modules/selectmodule.c --- a/Modules/selectmodule.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/selectmodule.c Fri Apr 15 14:51:10 2016 +0200 @@ -788,6 +788,9 @@ newPyEpoll_Object(PyTypeObject *type, in PyErr_SetFromErrno(PyExc_IOError); return NULL; } + if (fd == -1) { + _Py_try_set_non_inheritable(self->epfd); + } return (PyObject *)self; } @@ -1449,6 +1452,9 @@ newKqueue_Object(PyTypeObject *type, SOC PyErr_SetFromErrno(PyExc_IOError); return NULL; } + if (fd == -1) { + _Py_try_set_non_inheritable(self->kqfd); + } return (PyObject *)self; } diff -r 0f5eb87afd23 Modules/sunaudiodev.c --- a/Modules/sunaudiodev.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/sunaudiodev.c Fri Apr 15 14:51:10 2016 +0200 @@ -102,6 +102,7 @@ newsadobject(PyObject *args) PyMem_DEL(ctldev); return NULL; } + _Py_try_set_non_inheritable(fd); PyMem_DEL(ctldev); /* Create and initialize the object */ diff -r 0f5eb87afd23 Modules/zipimport.c --- a/Modules/zipimport.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Modules/zipimport.c Fri Apr 15 14:51:10 2016 +0200 @@ -725,7 +725,7 @@ read_directory(const char *archive) } strcpy(path, archive); - fp = fopen(archive, "rb"); + fp = _Py_fopen(archive, "rb"); if (fp == NULL) { PyErr_Format(ZipImportError, "can't open Zip file: " "'%.200s'", archive); @@ -936,7 +936,7 @@ get_data(const char *archive, PyObject * return NULL; } - fp = fopen(archive, "rb"); + fp = _Py_fopen(archive, "rb"); if (!fp) { PyErr_Format(PyExc_IOError, "zipimport: can not open file %s", archive); diff -r 0f5eb87afd23 PC/import_nt.c --- a/PC/import_nt.c Fri Apr 15 02:14:19 2016 +0000 +++ b/PC/import_nt.c Fri Apr 15 14:51:10 2016 +0200 @@ -79,8 +79,9 @@ FILE *PyWin_FindRegisteredModule(const c } if (fdp->suffix == NULL) return NULL; - fp = fopen(pathBuf, fdp->mode); - if (fp != NULL) + fp = _Py_fopen(pathBuf, fdp->mode); + if (fp != NULL) { *ppFileDesc = fdp; + } return fp; } diff -r 0f5eb87afd23 PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj Fri Apr 15 02:14:19 2016 +0000 +++ b/PCbuild/pythoncore.vcxproj Fri Apr 15 14:51:10 2016 +0200 @@ -101,6 +101,7 @@ + @@ -347,6 +348,7 @@ + diff -r 0f5eb87afd23 Parser/pgenmain.c --- a/Parser/pgenmain.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Parser/pgenmain.c Fri Apr 15 14:51:10 2016 +0200 @@ -58,6 +58,7 @@ main(int argc, char **argv) printf("Writing %s ...\n", graminit_c); printgrammar(g, fp); fclose(fp); + fp = fopen(graminit_h, "w"); if (fp == NULL) { perror(graminit_h); @@ -67,6 +68,7 @@ main(int argc, char **argv) printf("Writing %s ...\n", graminit_h); printnonterminals(g, fp); fclose(fp); + Py_Exit(0); return 0; /* Make gcc -Wall happy */ } @@ -88,6 +90,7 @@ getgrammar(char *filename) n = PyParser_ParseFile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &err); fclose(fp); + if (n == NULL) { fprintf(stderr, "Parsing error %d, line %d.\n", err.error, err.lineno); diff -r 0f5eb87afd23 Python/bltinmodule.c --- a/Python/bltinmodule.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/bltinmodule.c Fri Apr 15 14:51:10 2016 +0200 @@ -794,7 +794,7 @@ builtin_execfile(PyObject *self, PyObjec if (exists) { Py_BEGIN_ALLOW_THREADS - fp = fopen(filename, "r" PY_STDIOTEXTMODE); + fp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE); Py_END_ALLOW_THREADS if (fp == NULL) { diff -r 0f5eb87afd23 Python/errors.c --- a/Python/errors.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/errors.c Fri Apr 15 14:51:10 2016 +0200 @@ -798,7 +798,7 @@ PyErr_ProgramText(const char *filename, if (filename == NULL || *filename == '\0' || lineno <= 0) return NULL; - fp = fopen(filename, "r" PY_STDIOTEXTMODE); + fp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE); if (fp == NULL) return NULL; for (i = 0; i < lineno; i++) { diff -r 0f5eb87afd23 Python/fileutils.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/fileutils.c Fri Apr 15 14:51:10 2016 +0200 @@ -0,0 +1,57 @@ +#include "Python.h" + +#ifdef MS_WINDOWS +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif /* HAVE_FCNTL_H */ + +void +_Py_try_set_non_inheritable(int fd) +{ +#ifdef MS_WINDOWS + HANDLE handle; + DWORD flags; + + if (!_PyVerify_fd(fd)) { + return; + } + + handle = (HANDLE)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) { + return; + } + + (void)SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); +#else + int attr; + + attr = fcntl(fd, F_GETFD); + if (attr < 0) { + return; + } + + /* clear the FD_CLOEXEC flag (if it was set) */ + attr = attr & ~FD_CLOEXEC; + + (void)fcntl(fd, F_SETFD, attr); +#endif +} + +FILE* +_Py_fopen(const char *path, const char *mode) +{ + FILE *fp; + int fd; + + fp = fopen(path, mode); + if (fp == NULL) { + return NULL; + } + + fd = fileno(fp); + _Py_try_set_non_inheritable(fd); + return fp; +} diff -r 0f5eb87afd23 Python/import.c --- a/Python/import.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/import.c Fri Apr 15 14:51:10 2016 +0200 @@ -790,9 +790,10 @@ check_compiled_module(char *pathname, ti long magic; long pyc_mtime; - fp = fopen(cpathname, "rb"); + fp = _Py_fopen(cpathname, "rb"); if (fp == NULL) return NULL; + magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { if (Py_VerboseFlag) @@ -912,10 +913,11 @@ open_exclusive(char *filename, mode_t mo ); if (fd < 0) return NULL; + _Py_try_set_non_inheritable(fd); return fdopen(fd, "wb"); #else /* Best we can do -- on Windows this can't happen anyway */ - return fopen(filename, "wb"); + return _Py_fopen(filename, "wb"); #endif } @@ -3086,9 +3088,10 @@ get_file(char *pathname, PyObject *fob, if (fob == NULL) { if (mode[0] == 'U') mode = "r" PY_STDIOTEXTMODE; - fp = fopen(pathname, mode); - if (fp == NULL) + fp = _Py_fopen(pathname, mode); + if (fp == NULL) { PyErr_SetFromErrno(PyExc_IOError); + } } else { fp = PyFile_AsFile(fob); diff -r 0f5eb87afd23 Python/pythonrun.c --- a/Python/pythonrun.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/pythonrun.c Fri Apr 15 14:51:10 2016 +0200 @@ -936,10 +936,13 @@ PyRun_SimpleFileExFlags(FILE *fp, const /* Try to run a pyc file. First, re-open in binary */ if (closeit) fclose(fp); - if ((fp = fopen(filename, "rb")) == NULL) { + + fp = _Py_fopen(filename, "rb"); + if (fp == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); goto done; } + /* Turn on optimization if a .pyo file is given */ if (strcmp(ext, ".pyo") == 0) Py_OptimizeFlag = 1; diff -r 0f5eb87afd23 Python/random.c --- a/Python/random.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/random.c Fri Apr 15 14:51:10 2016 +0200 @@ -1,8 +1,8 @@ #include "Python.h" #ifdef MS_WINDOWS -#include +# include #else -#include +# include #endif #ifdef Py_DEBUG @@ -174,6 +174,7 @@ dev_urandom_noraise(unsigned char *buffe fd = open("/dev/urandom", O_RDONLY); if (fd < 0) Py_FatalError("Failed to open /dev/urandom"); + _Py_try_set_non_inheritable(fd); while (0 < size) { @@ -200,7 +201,6 @@ dev_urandom_python(char *buffer, Py_ssiz int fd; Py_ssize_t n; struct stat st; - int attr; if (size <= 0) return 0; @@ -234,11 +234,7 @@ dev_urandom_python(char *buffer, Py_ssiz } /* try to make the file descriptor non-inheritable, ignore errors */ - attr = fcntl(fd, F_GETFD); - if (attr >= 0) { - attr |= FD_CLOEXEC; - (void)fcntl(fd, F_SETFD, attr); - } + _Py_try_set_non_inheritable(fd); if (urandom_cache.fd >= 0) { /* urandom_fd was initialized by another thread while we were diff -r 0f5eb87afd23 Python/traceback.c --- a/Python/traceback.c Fri Apr 15 02:14:19 2016 +0000 +++ b/Python/traceback.c Fri Apr 15 14:51:10 2016 +0200 @@ -128,7 +128,7 @@ int return -1; /* This is needed by Emacs' compile command */ #define FMT " File \"%.500s\", line %d, in %.500s\n" - xfp = fopen(filename, "r" PY_STDIOTEXTMODE); + xfp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE); if (xfp == NULL) { /* Search tail of filename in sys.path before giving up */ PyObject *path; @@ -159,7 +159,7 @@ int if (len > 0 && namebuf[len-1] != SEP) namebuf[len++] = SEP; strcpy(namebuf+len, tail); - xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE); + xfp = _Py_fopen(namebuf, "r" PY_STDIOTEXTMODE); if (xfp != NULL) { break; }