[issue9504] signal.signal/signal.alarm not working as expected

Charles-Francois Natali report at bugs.python.org
Sun Jan 9 19:36:42 CET 2011


Charles-Francois Natali <neologix at free.fr> added the comment:

> Antoine Pitrou <pitrou at free.fr> added the comment:
>
> Charles-François' analysis seems to be right. Note that the actual issue here is that read() always succeeds, returning a partial result (because you're executing a command, 'find /', which outputs a lot of data). If read() were interrupted before anything could be read, it would return EINTR and the handler would get executed immediately.
>
> Anyone wants to propose a patch + tests?
>

Attached is a tentative patch: it checks for pending signals inside
_bufferedreader_read_generic, fileio_readall, and rawiobase_readall.
I tested quickly on regular files and on pipes, and handlers are now
called on time. As a an obvious bonus, it's also easier to interrupt a
script doing I/O with a KeyboardInterrupt (SIGINT).
If nothing seems blatantly wrong about this patch, I will go ahead and
try to write some tests for this.

Charles

> ----------
> versions: +Python 3.2
>
> _______________________________________
> Python tracker <report at bugs.python.org>
> <http://bugs.python.org/issue9504>
> _______________________________________
>

----------
keywords: +patch
Added file: http://bugs.python.org/file20327/io_signal.diff

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue9504>
_______________________________________
-------------- next part --------------
diff -urp A/Modules/_io/bufferedio.c B/Modules/_io/bufferedio.c
--- A/Modules/_io/bufferedio.c	2010-12-21 22:26:09.000000000 +0100
+++ B/Modules/_io/bufferedio.c	2011-01-09 18:46:01.000000000 +0100
@@ -1405,6 +1405,10 @@ _bufferedreader_read_generic(buffered *s
         }
         remaining -= r;
         written += r;
+        /* check pending signals */
+        if (PyErr_CheckSignals() < 0) {
+            goto error;
+        }
     }
     assert(remaining <= self->buffer_size);
     self->pos = 0;
@@ -1442,6 +1446,10 @@ _bufferedreader_read_generic(buffered *s
         }
         if (remaining == 0)
             break;
+        /* check pending signals */
+        if (PyErr_CheckSignals() < 0) {
+            goto error;
+        }
     }
 
     return res;
diff -urp A/Modules/_io/fileio.c B/Modules/_io/fileio.c
--- A/Modules/_io/fileio.c	2010-11-26 09:52:36.000000000 +0100
+++ B/Modules/_io/fileio.c	2011-01-09 19:26:52.000000000 +0100
@@ -583,6 +583,11 @@ fileio_readall(fileio *self)
             return NULL;
         }
         total += n;
+        /* check pending signals */
+        if (PyErr_CheckSignals() < 0) {
+            Py_DECREF(result);
+            return NULL;
+        }
     }
 
     if (PyBytes_GET_SIZE(result) > total) {
diff -urp A/Modules/_io/iobase.c B/Modules/_io/iobase.c
--- A/Modules/_io/iobase.c	2010-09-14 20:53:07.000000000 +0200
+++ B/Modules/_io/iobase.c	2011-01-09 19:27:15.000000000 +0100
@@ -831,6 +831,11 @@ rawiobase_readall(PyObject *self, PyObje
             Py_DECREF(chunks);
             return NULL;
         }
+        /* check pending signals */
+        if (PyErr_CheckSignals() < 0) {
+            Py_DECREF(chunks);
+            return NULL;
+        }
     }
     result = _PyBytes_Join(_PyIO_empty_bytes, chunks);
     Py_DECREF(chunks);


More information about the Python-bugs-list mailing list