Original patch by Hallvard B Furuseth.
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.
{
Py_buffer pbuf;
Py_ssize_t n, len;
+ int err;
if (self->fd < 0)
return err_closed();
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;
}
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;
}
{
Py_buffer pbuf;
Py_ssize_t n, len;
+ int err;
if (self->fd < 0)
return err_closed();
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;
}
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};
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)
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 = "<unprintable file name>";
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;
{
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) {
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;
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 */
/* 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);
* 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!
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;
}
my_fgets(char *buf, int len, FILE *fp)
{
char *p;
+ int err;
while (1) {
if (PyOS_InputHook != NULL)
(void)(PyOS_InputHook)();
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:
return -1; /* EOF */
}
#ifdef EINTR
- if (errno == EINTR) {
+ if (err == EINTR) {
int s;
#ifdef WITH_THREAD
PyEval_RestoreThread(_PyOS_ReadlineTState);