]> granicus.if.org Git - python/commitdiff
Issue #10350: Read and save errno before calling a function which might overwrite it.
authorAntoine Pitrou <solipsis@pitrou.net>
Fri, 16 Dec 2011 11:28:32 +0000 (12:28 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Fri, 16 Dec 2011 11:28:32 +0000 (12:28 +0100)
Original patch by Hallvard B Furuseth.

Misc/NEWS
Modules/_io/fileio.c
Modules/_multiprocessing/semaphore.c
Modules/main.c
Modules/readline.c
Modules/timemodule.c
Parser/myreadline.c

index 8b434137773b7750f91aa5f6195e7a0168e67011..94af4462b9bc7589b52c29b0a7a582a538c574f2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -97,6 +97,9 @@ Core and Builtins
 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.
 
index be5c9f8da9774b3535b74a7649ba64efaa036288..f39f8b0d879558752717874ea79b06e5f9bc3c82 100644 (file)
@@ -506,6 +506,7 @@ fileio_readinto(fileio *self, PyObject *args)
 {
     Py_buffer pbuf;
     Py_ssize_t n, len;
+    int err;
 
     if (self->fd < 0)
         return err_closed();
@@ -529,10 +530,12 @@ fileio_readinto(fileio *self, PyObject *args)
         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;
     }
@@ -675,9 +678,11 @@ fileio_read(fileio *self, PyObject *args)
         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;
     }
@@ -697,6 +702,7 @@ fileio_write(fileio *self, PyObject *args)
 {
     Py_buffer pbuf;
     Py_ssize_t n, len;
+    int err;
 
     if (self->fd < 0)
         return err_closed();
@@ -727,12 +733,14 @@ fileio_write(fileio *self, PyObject *args)
         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;
     }
index c2cd9148123bf09aa119f5930ce2f3620b3808ae..1f37d6ac37756f078b95ea667c92f5a64b90f871 100644 (file)
@@ -267,7 +267,7 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)
 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};
@@ -313,11 +313,13 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
         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)
index fcd9330e41d92cd2cf3e824d8d2d03bbf2c7c7a3..5a985a5c16f8aeb3235cfe5fa0d46d992b7aa622 100644 (file)
@@ -654,13 +654,14 @@ Py_Main(int argc, wchar_t **argv)
             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;
index 8337956648384083f63a0a9758a319496ea5d04a..4d54dade5d3f80c21ef03e333c823778be3ccf4f 100644 (file)
@@ -154,6 +154,7 @@ write_history_file(PyObject *self, PyObject *args)
 {
     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 @@ write_history_file(PyObject *self, PyObject *args)
         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;
@@ -970,7 +972,7 @@ readline_until_enter_or_signal(char *prompt, int *signal)
     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 */
@@ -984,13 +986,14 @@ readline_until_enter_or_signal(char *prompt, int *signal)
             /* 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);
index 33751fad500a0574041cf46b4cefbd9682c439f8..17d9c38d84c8925f01246714f3af0ec4b059ed41 100644 (file)
@@ -527,12 +527,14 @@ time_strftime(PyObject *self, PyObject *args)
      * 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!
@@ -550,7 +552,7 @@ time_strftime(PyObject *self, PyObject *args)
         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;
         }
index fb4b805e20d79dac6cb91dab131e4debe7e4bdc7..33d5b3d4cc402cd4e105d99b472d874fffd038fd 100644 (file)
@@ -36,6 +36,7 @@ static int
 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 @@ my_fgets(char *buf, int len, FILE *fp)
         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 @@ my_fgets(char *buf, int len, FILE *fp)
             return -1; /* EOF */
         }
 #ifdef EINTR
-        if (errno == EINTR) {
+        if (err == EINTR) {
             int s;
 #ifdef WITH_THREAD
             PyEval_RestoreThread(_PyOS_ReadlineTState);