Skip to content

Commit a3c0202

Browse files
committed
Issue #23708: Save/restore errno in _Py_read() and _Py_write()
Save and then restore errno because PyErr_CheckSignals() and PyErr_SetFromErrno() can modify it.
1 parent f50e187 commit a3c0202

1 file changed

Lines changed: 21 additions & 15 deletions

File tree

‎Python/fileutils.c‎

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,7 @@ Py_ssize_t
11371137
_Py_read(int fd, void *buf, size_t count)
11381138
{
11391139
Py_ssize_t n;
1140+
int err;
11401141
int async_err = 0;
11411142

11421143
/* _Py_read() must not be called with an exception set, otherwise the
@@ -1145,8 +1146,10 @@ _Py_read(int fd, void *buf, size_t count)
11451146
assert(!PyErr_Occurred());
11461147

11471148
if (!_PyVerify_fd(fd)) {
1149+
/* save/restore errno because PyErr_SetFromErrno() can modify it */
1150+
err = errno;
11481151
PyErr_SetFromErrno(PyExc_OSError);
1149-
assert(errno == EBADF);
1152+
errno = err;
11501153
return -1;
11511154
}
11521155

@@ -1171,23 +1174,23 @@ _Py_read(int fd, void *buf, size_t count)
11711174
#else
11721175
n = read(fd, buf, count);
11731176
#endif
1177+
/* save/restore errno because PyErr_CheckSignals()
1178+
* and PyErr_SetFromErrno() can modify it */
1179+
err = errno;
11741180
Py_END_ALLOW_THREADS
1175-
} while (n < 0 && errno == EINTR &&
1181+
} while (n < 0 && err == EINTR &&
11761182
!(async_err = PyErr_CheckSignals()));
11771183

11781184
if (async_err) {
11791185
/* read() was interrupted by a signal (failed with EINTR)
11801186
* and the Python signal handler raised an exception */
1181-
assert(errno == EINTR);
1182-
assert(PyErr_Occurred());
1187+
errno = err;
1188+
assert(errno == EINTR && PyErr_Occurred());
11831189
return -1;
11841190
}
11851191
if (n < 0) {
1186-
#ifndef NDEBUG
1187-
int err = errno;
1188-
#endif
11891192
PyErr_SetFromErrno(PyExc_OSError);
1190-
assert(errno == err);
1193+
errno = err;
11911194
return -1;
11921195
}
11931196

@@ -1209,6 +1212,7 @@ Py_ssize_t
12091212
_Py_write(int fd, const void *buf, size_t count)
12101213
{
12111214
Py_ssize_t n;
1215+
int err;
12121216
int async_err = 0;
12131217

12141218
/* _Py_write() must not be called with an exception set, otherwise the
@@ -1217,8 +1221,10 @@ _Py_write(int fd, const void *buf, size_t count)
12171221
assert(!PyErr_Occurred());
12181222

12191223
if (!_PyVerify_fd(fd)) {
1224+
/* save/restore errno because PyErr_SetFromErrno() can modify it */
1225+
err = errno;
12201226
PyErr_SetFromErrno(PyExc_OSError);
1221-
assert(errno == EBADF);
1227+
errno = err;
12221228
return -1;
12231229
}
12241230

@@ -1248,23 +1254,23 @@ _Py_write(int fd, const void *buf, size_t count)
12481254
#else
12491255
n = write(fd, buf, count);
12501256
#endif
1257+
/* save/restore errno because PyErr_CheckSignals()
1258+
* and PyErr_SetFromErrno() can modify it */
1259+
err = errno;
12511260
Py_END_ALLOW_THREADS
12521261
} while (n < 0 && errno == EINTR &&
12531262
!(async_err = PyErr_CheckSignals()));
12541263

12551264
if (async_err) {
12561265
/* write() was interrupted by a signal (failed with EINTR)
12571266
* and the Python signal handler raised an exception */
1258-
assert(errno == EINTR);
1259-
assert(PyErr_Occurred());
1267+
errno = err;
1268+
assert(errno == EINTR && PyErr_Occurred());
12601269
return -1;
12611270
}
12621271
if (n < 0) {
1263-
#ifndef NDEBUG
1264-
int err = errno;
1265-
#endif
12661272
PyErr_SetFromErrno(PyExc_OSError);
1267-
assert(errno == err);
1273+
errno = err;
12681274
return -1;
12691275
}
12701276

0 commit comments

Comments
 (0)