Issue #10350: Read and save errno before calling a function which might overwrite it.

Original patch by Hallvard B Furuseth.
This commit is contained in:
Antoine Pitrou 2011-12-16 12:28:32 +01:00
parent 87448819ab
commit c345ce1a69
7 changed files with 33 additions and 12 deletions

View File

@ -97,6 +97,9 @@ Core and Builtins
Library 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 - Issue #13591: A bug in importlib has been fixed that caused import_module
to load a module twice. to load a module twice.

View File

@ -506,6 +506,7 @@ fileio_readinto(fileio *self, PyObject *args)
{ {
Py_buffer pbuf; Py_buffer pbuf;
Py_ssize_t n, len; Py_ssize_t n, len;
int err;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
@ -529,10 +530,12 @@ fileio_readinto(fileio *self, PyObject *args)
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} else } else
n = -1; n = -1;
err = errno;
PyBuffer_Release(&pbuf); PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (err == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
errno = err;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
@ -675,9 +678,11 @@ fileio_read(fileio *self, PyObject *args)
n = -1; n = -1;
if (n < 0) { if (n < 0) {
int err = errno;
Py_DECREF(bytes); Py_DECREF(bytes);
if (errno == EAGAIN) if (err == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
errno = err;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
@ -697,6 +702,7 @@ fileio_write(fileio *self, PyObject *args)
{ {
Py_buffer pbuf; Py_buffer pbuf;
Py_ssize_t n, len; Py_ssize_t n, len;
int err;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
@ -727,12 +733,14 @@ fileio_write(fileio *self, PyObject *args)
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} else } else
n = -1; n = -1;
err = errno;
PyBuffer_Release(&pbuf); PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (err == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
errno = err;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }

View File

@ -267,7 +267,7 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)
static PyObject * static PyObject *
semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
{ {
int blocking = 1, res; int blocking = 1, res, err = 0;
double timeout; double timeout;
PyObject *timeout_obj = Py_None; PyObject *timeout_obj = Py_None;
struct timespec deadline = {0}; struct timespec deadline = {0};
@ -313,11 +313,13 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
else else
res = sem_timedwait(self->handle, &deadline); res = sem_timedwait(self->handle, &deadline);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
err = errno;
if (res == MP_EXCEPTION_HAS_BEEN_SET) if (res == MP_EXCEPTION_HAS_BEEN_SET)
break; break;
} while (res < 0 && errno == EINTR && !PyErr_CheckSignals()); } while (res < 0 && errno == EINTR && !PyErr_CheckSignals());
if (res < 0) { if (res < 0) {
errno = err;
if (errno == EAGAIN || errno == ETIMEDOUT) if (errno == EAGAIN || errno == ETIMEDOUT)
Py_RETURN_FALSE; Py_RETURN_FALSE;
else if (errno == EINTR) else if (errno == EINTR)

View File

@ -654,13 +654,14 @@ Py_Main(int argc, wchar_t **argv)
if (fp == NULL) { if (fp == NULL) {
char *cfilename_buffer; char *cfilename_buffer;
const char *cfilename; const char *cfilename;
int err = errno;
cfilename_buffer = _Py_wchar2char(filename, NULL); cfilename_buffer = _Py_wchar2char(filename, NULL);
if (cfilename_buffer != NULL) if (cfilename_buffer != NULL)
cfilename = cfilename_buffer; cfilename = cfilename_buffer;
else else
cfilename = "<unprintable file name>"; cfilename = "<unprintable file name>";
fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", 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) if (cfilename_buffer)
PyMem_Free(cfilename_buffer); PyMem_Free(cfilename_buffer);
return 2; return 2;

View File

@ -154,6 +154,7 @@ write_history_file(PyObject *self, PyObject *args)
{ {
PyObject *filename_obj = Py_None, *filename_bytes; PyObject *filename_obj = Py_None, *filename_bytes;
char *filename; char *filename;
int err;
if (!PyArg_ParseTuple(args, "|O:write_history_file", &filename_obj)) if (!PyArg_ParseTuple(args, "|O:write_history_file", &filename_obj))
return NULL; return NULL;
if (filename_obj != Py_None) { if (filename_obj != Py_None) {
@ -164,10 +165,11 @@ write_history_file(PyObject *self, PyObject *args)
filename_bytes = NULL; filename_bytes = NULL;
filename = NULL; filename = NULL;
} }
errno = write_history(filename); errno = err = write_history(filename);
if (!errno && _history_length >= 0) if (!err && _history_length >= 0)
history_truncate_file(filename, _history_length); history_truncate_file(filename, _history_length);
Py_XDECREF(filename_bytes); Py_XDECREF(filename_bytes);
errno = err;
if (errno) if (errno)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -970,7 +972,7 @@ readline_until_enter_or_signal(char *prompt, int *signal)
completed_input_string = not_done_reading; completed_input_string = not_done_reading;
while (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) while (!has_input)
{ struct timeval timeout = {0, 100000}; /* 0.1 seconds */ { 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 */ /* select resets selectset if no input was available */
has_input = select(fileno(rl_instream) + 1, &selectset, has_input = select(fileno(rl_instream) + 1, &selectset,
NULL, NULL, timeoutp); NULL, NULL, timeoutp);
err = errno;
if(PyOS_InputHook) PyOS_InputHook(); if(PyOS_InputHook) PyOS_InputHook();
} }
if(has_input > 0) { if (has_input > 0) {
rl_callback_read_char(); rl_callback_read_char();
} }
else if (errno == EINTR) { else if (err == EINTR) {
int s; int s;
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyEval_RestoreThread(_PyOS_ReadlineTState); PyEval_RestoreThread(_PyOS_ReadlineTState);

View File

@ -527,12 +527,14 @@ time_strftime(PyObject *self, PyObject *args)
* will be ahead of time... * will be ahead of time...
*/ */
for (i = 1024; ; i += i) { for (i = 1024; ; i += i) {
int err;
outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char)); outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char));
if (outbuf == NULL) { if (outbuf == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
break; break;
} }
buflen = format_time(outbuf, i, fmt, &buf); buflen = format_time(outbuf, i, fmt, &buf);
err = errno;
if (buflen > 0 || i >= 256 * fmtlen) { if (buflen > 0 || i >= 256 * fmtlen) {
/* If the buffer is 256 times as long as the format, /* If the buffer is 256 times as long as the format,
it's probably not failing for lack of room! it's probably not failing for lack of room!
@ -550,7 +552,7 @@ time_strftime(PyObject *self, PyObject *args)
PyMem_Free(outbuf); PyMem_Free(outbuf);
#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
/* VisualStudio .NET 2005 does this properly */ /* VisualStudio .NET 2005 does this properly */
if (buflen == 0 && errno == EINVAL) { if (buflen == 0 && err == EINVAL) {
PyErr_SetString(PyExc_ValueError, "Invalid format string"); PyErr_SetString(PyExc_ValueError, "Invalid format string");
break; break;
} }

View File

@ -36,6 +36,7 @@ static int
my_fgets(char *buf, int len, FILE *fp) my_fgets(char *buf, int len, FILE *fp)
{ {
char *p; char *p;
int err;
while (1) { while (1) {
if (PyOS_InputHook != NULL) if (PyOS_InputHook != NULL)
(void)(PyOS_InputHook)(); (void)(PyOS_InputHook)();
@ -44,6 +45,7 @@ my_fgets(char *buf, int len, FILE *fp)
p = fgets(buf, len, fp); p = fgets(buf, len, fp);
if (p != NULL) if (p != NULL)
return 0; /* No error */ return 0; /* No error */
err = errno;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* In the case of a Ctrl+C or some other external event /* In the case of a Ctrl+C or some other external event
interrupting the operation: interrupting the operation:
@ -78,7 +80,7 @@ my_fgets(char *buf, int len, FILE *fp)
return -1; /* EOF */ return -1; /* EOF */
} }
#ifdef EINTR #ifdef EINTR
if (errno == EINTR) { if (err == EINTR) {
int s; int s;
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyEval_RestoreThread(_PyOS_ReadlineTState); PyEval_RestoreThread(_PyOS_ReadlineTState);