call close on the underlying stream even if flush raises (closes #16597)

Patch by Serhiy Storchaka.
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 334734b..b077f34 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -484,7 +484,7 @@
 static PyObject *
 buffered_close(buffered *self, PyObject *args)
 {
-    PyObject *res = NULL;
+    PyObject *res = NULL, *exc = NULL, *val, *tb;
     int r;
 
     CHECK_INITIALIZED(self)
@@ -512,13 +512,29 @@
     res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
     if (!ENTER_BUFFERED(self))
         return NULL;
-    if (res == NULL) {
-        goto end;
-    }
-    Py_XDECREF(res);
+    if (res == NULL)
+        PyErr_Fetch(&exc, &val, &tb);
+    else
+        Py_DECREF(res);
 
     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
 
+    if (exc != NULL) {
+        if (res != NULL) {
+            Py_CLEAR(res);
+            PyErr_Restore(exc, val, tb);
+        }
+        else {
+            PyObject *val2;
+            Py_DECREF(exc);
+            Py_XDECREF(tb);
+            PyErr_Fetch(&exc, &val2, &tb);
+            PyErr_NormalizeException(&exc, &val2, &tb);
+            PyException_SetContext(val2, val);
+            PyErr_Restore(exc, val2, tb);
+        }
+    }
+
 end:
     LEAVE_BUFFERED(self)
     return res;
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 96434a8..83437d6 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -2554,6 +2554,7 @@
         Py_RETURN_NONE; /* stream already closed */
     }
     else {
+        PyObject *exc = NULL, *val, *tb;
         if (self->deallocating) {
             res = _PyObject_CallMethodId(self->buffer, &PyId__dealloc_warn, "O", self);
             if (res)
@@ -2562,13 +2563,28 @@
                 PyErr_Clear();
         }
         res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL);
-        if (res == NULL) {
-            return NULL;
-        }
+        if (res == NULL)
+            PyErr_Fetch(&exc, &val, &tb);
         else
             Py_DECREF(res);
 
-        return _PyObject_CallMethodId(self->buffer, &PyId_close, NULL);
+        res = _PyObject_CallMethodId(self->buffer, &PyId_close, NULL);
+        if (exc != NULL) {
+            if (res != NULL) {
+                Py_CLEAR(res);
+                PyErr_Restore(exc, val, tb);
+            }
+            else {
+                PyObject *val2;
+                Py_DECREF(exc);
+                Py_XDECREF(tb);
+                PyErr_Fetch(&exc, &val2, &tb);
+                PyErr_NormalizeException(&exc, &val2, &tb);
+                PyException_SetContext(val2, val);
+                PyErr_Restore(exc, val2, tb);
+            }
+        }
+        return res;
     }
 }