[Python-checkins] cpython (merge 3.2 -> default): Issue #10350: Read and save errno before calling a function which might

antoine.pitrou python-checkins at python.org
Fri Dec 16 12:32:41 CET 2011


http://hg.python.org/cpython/rev/8e0b2e75ca7a
changeset:   73997:8e0b2e75ca7a
parent:      73995:ffe981aeb06f
parent:      73996:6a966179c73a
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Fri Dec 16 12:29:37 2011 +0100
summary:
  Issue #10350: Read and save errno before calling a function which might overwrite it.
Original patch by Hallvard B Furuseth.

files:
  Misc/NEWS                            |   3 +++
  Modules/_io/fileio.c                 |  14 +++++++++++---
  Modules/_multiprocessing/semaphore.c |   4 +++-
  Modules/main.c                       |   3 ++-
  Modules/readline.c                   |  13 ++++++++-----
  Modules/timemodule.c                 |   4 +++-
  Parser/myreadline.c                  |   4 +++-
  7 files changed, 33 insertions(+), 12 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -419,6 +419,9 @@
 Library
 -------
 
+- Issue #10350: Read and save errno before calling a function which might
+  overwrite it.  Original patch by Hallvard B Furuseth.
+
 - Issue #11610: Introduce a more general way to declare abstract properties.
 
 - Issue #13591: A bug in importlib has been fixed that caused import_module
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -530,6 +530,7 @@
 {
     Py_buffer pbuf;
     Py_ssize_t n, len;
+    int err;
 
     if (self->fd < 0)
         return err_closed();
@@ -553,10 +554,12 @@
         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;
     }
@@ -726,9 +729,11 @@
         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;
     }
@@ -748,6 +753,7 @@
 {
     Py_buffer pbuf;
     Py_ssize_t n, len;
+    int err;
 
     if (self->fd < 0)
         return err_closed();
@@ -778,12 +784,14 @@
         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;
     }
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
--- a/Modules/_multiprocessing/semaphore.c
+++ b/Modules/_multiprocessing/semaphore.c
@@ -255,7 +255,7 @@
 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};
@@ -301,11 +301,13 @@
         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)
diff --git a/Modules/main.c b/Modules/main.c
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -655,13 +655,14 @@
             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;
diff --git a/Modules/readline.c b/Modules/readline.c
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -154,6 +154,7 @@
 {
     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) {
@@ -164,10 +165,11 @@
         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;
@@ -969,7 +971,7 @@
     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 */
@@ -983,13 +985,14 @@
             /* 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);
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -515,12 +515,14 @@
      * 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!
@@ -538,7 +540,7 @@
         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;
         }
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -36,6 +36,7 @@
 my_fgets(char *buf, int len, FILE *fp)
 {
     char *p;
+    int err;
     while (1) {
         if (PyOS_InputHook != NULL)
             (void)(PyOS_InputHook)();
@@ -44,6 +45,7 @@
         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:
@@ -78,7 +80,7 @@
             return -1; /* EOF */
         }
 #ifdef EINTR
-        if (errno == EINTR) {
+        if (err == EINTR) {
             int s;
 #ifdef WITH_THREAD
             PyEval_RestoreThread(_PyOS_ReadlineTState);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list