Kaydet (Commit) 16b11de0 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Merged revisions 84239 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r84239 | antoine.pitrou | 2010-08-21 21:09:32 +0200 (sam., 21 août 2010) | 4 lines

  Issue #9617: Signals received during a low-level write operation aren't
  ignored by the buffered IO layer anymore.
........
üst 8dcc96c9
...@@ -30,6 +30,8 @@ import warnings ...@@ -30,6 +30,8 @@ import warnings
import weakref import weakref
import gc import gc
import abc import abc
import signal
import errno
from itertools import chain, cycle, count from itertools import chain, cycle, count
from collections import deque from collections import deque
from test import support from test import support
...@@ -2470,6 +2472,75 @@ class CMiscIOTest(MiscIOTest): ...@@ -2470,6 +2472,75 @@ class CMiscIOTest(MiscIOTest):
class PyMiscIOTest(MiscIOTest): class PyMiscIOTest(MiscIOTest):
io = pyio io = pyio
@unittest.skipIf(os.name == 'nt', 'POSIX signals required for this test.')
class SignalsTest(unittest.TestCase):
def setUp(self):
self.oldalrm = signal.signal(signal.SIGALRM, self.alarm_interrupt)
def tearDown(self):
signal.signal(signal.SIGALRM, self.oldalrm)
def alarm_interrupt(self, sig, frame):
1/0
@unittest.skipUnless(threading, 'Threading required for this test.')
def check_interrupted_write(self, item, bytes, **fdopen_kwargs):
"""Check that a partial write, when it gets interrupted, properly
invokes the signal handler."""
read_results = []
def _read():
s = os.read(r, 1)
read_results.append(s)
t = threading.Thread(target=_read)
t.daemon = True
r, w = os.pipe()
try:
wio = self.io.open(w, **fdopen_kwargs)
t.start()
signal.alarm(1)
# Fill the pipe enough that the write will be blocking.
# It will be interrupted by the timer armed above. Since the
# other thread has read one byte, the low-level write will
# return with a successful (partial) result rather than an EINTR.
# The buffered IO layer must check for pending signal
# handlers, which in this case will invoke alarm_interrupt().
self.assertRaises(ZeroDivisionError,
wio.write, item * (1024 * 1024))
t.join()
# We got one byte, get another one and check that it isn't a
# repeat of the first one.
read_results.append(os.read(r, 1))
self.assertEqual(read_results, [bytes[0:1], bytes[1:2]])
finally:
os.close(w)
os.close(r)
# This is deliberate. If we didn't close the file descriptor
# before closing wio, wio would try to flush its internal
# buffer, and block again.
try:
wio.close()
except IOError as e:
if e.errno != errno.EBADF:
raise
def test_interrupted_write_unbuffered(self):
self.check_interrupted_write(b"xy", b"xy", mode="wb", buffering=0)
def test_interrupted_write_buffered(self):
self.check_interrupted_write(b"xy", b"xy", mode="wb")
def test_interrupted_write_text(self):
self.check_interrupted_write("xy", b"xy", mode="w", encoding="ascii")
class CSignalsTest(SignalsTest):
io = io
class PySignalsTest(SignalsTest):
io = pyio
def test_main(): def test_main():
tests = (CIOTest, PyIOTest, tests = (CIOTest, PyIOTest,
CBufferedReaderTest, PyBufferedReaderTest, CBufferedReaderTest, PyBufferedReaderTest,
...@@ -2479,7 +2550,9 @@ def test_main(): ...@@ -2479,7 +2550,9 @@ def test_main():
StatefulIncrementalDecoderTest, StatefulIncrementalDecoderTest,
CIncrementalNewlineDecoderTest, PyIncrementalNewlineDecoderTest, CIncrementalNewlineDecoderTest, PyIncrementalNewlineDecoderTest,
CTextIOWrapperTest, PyTextIOWrapperTest, CTextIOWrapperTest, PyTextIOWrapperTest,
CMiscIOTest, PyMiscIOTest,) CMiscIOTest, PyMiscIOTest,
CSignalsTest, PySignalsTest,
)
# Put the namespaces of the IO module we are testing and some useful mock # Put the namespaces of the IO module we are testing and some useful mock
# classes in the __dict__ of each test. # classes in the __dict__ of each test.
......
...@@ -95,6 +95,9 @@ C-API ...@@ -95,6 +95,9 @@ C-API
Library Library
------- -------
- Issue #9617: Signals received during a low-level write operation aren't
ignored by the buffered IO layer anymore.
- Issue #9605: posix.getlogin() decodes the username with file filesystem - Issue #9605: posix.getlogin() decodes the username with file filesystem
encoding and surrogateescape error handler. Patch written by David Watson. encoding and surrogateescape error handler. Patch written by David Watson.
......
...@@ -1661,6 +1661,11 @@ _bufferedwriter_flush_unlocked(buffered *self, int restore_pos) ...@@ -1661,6 +1661,11 @@ _bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
self->write_pos += n; self->write_pos += n;
self->raw_pos = self->write_pos; self->raw_pos = self->write_pos;
written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t); written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
/* Partial writes can return successfully when interrupted by a
signal (see write(2)). We must run signal handlers before
blocking another time, possibly indefinitely. */
if (PyErr_CheckSignals() < 0)
goto error;
} }
if (restore_pos) { if (restore_pos) {
...@@ -1797,6 +1802,11 @@ bufferedwriter_write(buffered *self, PyObject *args) ...@@ -1797,6 +1802,11 @@ bufferedwriter_write(buffered *self, PyObject *args)
} }
written += n; written += n;
remaining -= n; remaining -= n;
/* Partial writes can return successfully when interrupted by a
signal (see write(2)). We must run signal handlers before
blocking another time, possibly indefinitely. */
if (PyErr_CheckSignals() < 0)
goto error;
} }
if (self->readable) if (self->readable)
_bufferedreader_reset_buf(self); _bufferedreader_reset_buf(self);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment