From c345ce1a69b3c4a46d87ef56d859bc70abfc74b4 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Dec 2011 12:28:32 +0100 Subject: Issue #10350: Read and save errno before calling a function which might overwrite it. Original patch by Hallvard B Furuseth. --- Misc/NEWS | 3 +++ Modules/_io/fileio.c | 14 +++++++++++--- Modules/_multiprocessing/semaphore.c | 4 +++- Modules/main.c | 3 ++- Modules/readline.c | 13 ++++++++----- Modules/timemodule.c | 4 +++- Parser/myreadline.c | 4 +++- 7 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 8b43413..94af446 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -97,6 +97,9 @@ Core and Builtins Library ------- +- Issue #10350: Read and save errno before calling a function which might + overwrite it. Original patch by Hallvard B Furuseth. + - Issue #13591: A bug in importlib has been fixed that caused import_module to load a module twice. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index be5c9f8..f39f8b0 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -506,6 +506,7 @@ fileio_readinto(fileio *self, PyObject *args) { Py_buffer pbuf; Py_ssize_t n, len; + int err; if (self->fd < 0) return err_closed(); @@ -529,10 +530,12 @@ fileio_readinto(fileio *self, PyObject *args) Py_END_ALLOW_THREADS } else n = -1; + err = errno; PyBuffer_Release(&pbuf); if (n < 0) { - if (errno == EAGAIN) + if (err == EAGAIN) Py_RETURN_NONE; + errno = err; PyErr_SetFromErrno(PyExc_IOError); return NULL; } @@ -675,9 +678,11 @@ fileio_read(fileio *self, PyObject *args) n = -1; if (n < 0) { + int err = errno; Py_DECREF(bytes); - if (errno == EAGAIN) + if (err == EAGAIN) Py_RETURN_NONE; + errno = err; PyErr_SetFromErrno(PyExc_IOError); return NULL; } @@ -697,6 +702,7 @@ fileio_write(fileio *self, PyObject *args) { Py_buffer pbuf; Py_ssize_t n, len; + int err; if (self->fd < 0) return err_closed(); @@ -727,12 +733,14 @@ fileio_write(fileio *self, PyObject *args) Py_END_ALLOW_THREADS } else n = -1; + err = errno; PyBuffer_Release(&pbuf); if (n < 0) { - if (errno == EAGAIN) + if (err == EAGAIN) Py_RETURN_NONE; + errno = err; PyErr_SetFromErrno(PyExc_IOError); return NULL; } diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index c2cd914..1f37d6a 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -267,7 +267,7 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) static PyObject * semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) { - int blocking = 1, res; + int blocking = 1, res, err = 0; double timeout; PyObject *timeout_obj = Py_None; struct timespec deadline = {0}; @@ -313,11 +313,13 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) else res = sem_timedwait(self->handle, &deadline); Py_END_ALLOW_THREADS + err = errno; if (res == MP_EXCEPTION_HAS_BEEN_SET) break; } while (res < 0 && errno == EINTR && !PyErr_CheckSignals()); if (res < 0) { + errno = err; if (errno == EAGAIN || errno == ETIMEDOUT) Py_RETURN_FALSE; else if (errno == EINTR) diff --git a/Modules/main.c b/Modules/main.c index fcd9330..5a985a5 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -654,13 +654,14 @@ Py_Main(int argc, wchar_t **argv) if (fp == NULL) { char *cfilename_buffer; const char *cfilename; + int err = errno; cfilename_buffer = _Py_wchar2char(filename, NULL); if (cfilename_buffer != NULL) cfilename = cfilename_buffer; else cfilename = ""; fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", - argv[0], cfilename, errno, strerror(errno)); + argv[0], cfilename, err, strerror(err)); if (cfilename_buffer) PyMem_Free(cfilename_buffer); return 2; diff --git a/Modules/readline.c b/Modules/readline.c index 8337956..4d54dad 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -154,6 +154,7 @@ write_history_file(PyObject *self, PyObject *args) { PyObject *filename_obj = Py_None, *filename_bytes; char *filename; + int err; if (!PyArg_ParseTuple(args, "|O:write_history_file", &filename_obj)) return NULL; if (filename_obj != Py_None) { @@ -164,10 +165,11 @@ write_history_file(PyObject *self, PyObject *args) filename_bytes = NULL; filename = NULL; } - errno = write_history(filename); - if (!errno && _history_length >= 0) + errno = err = write_history(filename); + if (!err && _history_length >= 0) history_truncate_file(filename, _history_length); Py_XDECREF(filename_bytes); + errno = err; if (errno) return PyErr_SetFromErrno(PyExc_IOError); Py_RETURN_NONE; @@ -970,7 +972,7 @@ readline_until_enter_or_signal(char *prompt, int *signal) completed_input_string = not_done_reading; while (completed_input_string == not_done_reading) { - int has_input = 0; + int has_input = 0, err = 0; while (!has_input) { struct timeval timeout = {0, 100000}; /* 0.1 seconds */ @@ -984,13 +986,14 @@ readline_until_enter_or_signal(char *prompt, int *signal) /* select resets selectset if no input was available */ has_input = select(fileno(rl_instream) + 1, &selectset, NULL, NULL, timeoutp); + err = errno; if(PyOS_InputHook) PyOS_InputHook(); } - if(has_input > 0) { + if (has_input > 0) { rl_callback_read_char(); } - else if (errno == EINTR) { + else if (err == EINTR) { int s; #ifdef WITH_THREAD PyEval_RestoreThread(_PyOS_ReadlineTState); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 33751fa..17d9c38 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -527,12 +527,14 @@ time_strftime(PyObject *self, PyObject *args) * will be ahead of time... */ for (i = 1024; ; i += i) { + int err; outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char)); if (outbuf == NULL) { PyErr_NoMemory(); break; } buflen = format_time(outbuf, i, fmt, &buf); + err = errno; if (buflen > 0 || i >= 256 * fmtlen) { /* If the buffer is 256 times as long as the format, it's probably not failing for lack of room! @@ -550,7 +552,7 @@ time_strftime(PyObject *self, PyObject *args) PyMem_Free(outbuf); #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) /* VisualStudio .NET 2005 does this properly */ - if (buflen == 0 && errno == EINVAL) { + if (buflen == 0 && err == EINVAL) { PyErr_SetString(PyExc_ValueError, "Invalid format string"); break; } diff --git a/Parser/myreadline.c b/Parser/myreadline.c index fb4b805..33d5b3d 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -36,6 +36,7 @@ static int my_fgets(char *buf, int len, FILE *fp) { char *p; + int err; while (1) { if (PyOS_InputHook != NULL) (void)(PyOS_InputHook)(); @@ -44,6 +45,7 @@ my_fgets(char *buf, int len, FILE *fp) p = fgets(buf, len, fp); if (p != NULL) return 0; /* No error */ + err = errno; #ifdef MS_WINDOWS /* In the case of a Ctrl+C or some other external event interrupting the operation: @@ -78,7 +80,7 @@ my_fgets(char *buf, int len, FILE *fp) return -1; /* EOF */ } #ifdef EINTR - if (errno == EINTR) { + if (err == EINTR) { int s; #ifdef WITH_THREAD PyEval_RestoreThread(_PyOS_ReadlineTState); -- cgit v0.12