mirror of https://github.com/python/cpython
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:
parent
87448819ab
commit
c345ce1a69
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue