MCPcopy Index your code
hub / github.com/python/cpython / check_interrupted_write_retry

Method check_interrupted_write_retry

Lib/test/test_io/test_signals.py:192–258  ·  view source on GitHub ↗

Check that a buffered write, when it gets interrupted (either returning a partial result or EINTR), properly invokes the signal handler and retries if the latter returned successfully.

(self, item, **fdopen_kwargs)

Source from the content-addressed store, hash-verified

190 mode="r", encoding="latin1")
191
192 def check_interrupted_write_retry(self, item, **fdopen_kwargs):
193 """Check that a buffered write, when it gets interrupted (either
194 returning a partial result or EINTR), properly invokes the signal
195 handler and retries if the latter returned successfully."""
196 select = import_helper.import_module("select")
197
198 # A quantity that exceeds the buffer size of an anonymous pipe's
199 # write end.
200 N = support.PIPE_MAX_SIZE
201 r, w = os.pipe()
202 fdopen_kwargs["closefd"] = False
203
204 # We need a separate thread to read from the pipe and allow the
205 # write() to finish. This thread is started after the SIGALRM is
206 # received (forcing a first EINTR in write()).
207 read_results = []
208 write_finished = False
209 error = None
210 def _read():
211 try:
212 while not write_finished:
213 while r in select.select([r], [], [], 1.0)[0]:
214 s = os.read(r, 1024)
215 read_results.append(s)
216 except BaseException as exc:
217 nonlocal error
218 error = exc
219 t = threading.Thread(target=_read)
220 t.daemon = True
221 def alarm1(sig, frame):
222 signal.signal(signal.SIGALRM, alarm2)
223 signal.alarm(1)
224 def alarm2(sig, frame):
225 t.start()
226
227 large_data = item * N
228 signal.signal(signal.SIGALRM, alarm1)
229 try:
230 wio = self.io.open(w, **fdopen_kwargs)
231 signal.alarm(1)
232 # Expected behaviour:
233 # - first raw write() is partial (because of the limited pipe buffer
234 # and the first alarm)
235 # - second raw write() returns EINTR (because of the second alarm)
236 # - subsequent write()s are successful (either partial or complete)
237 written = wio.write(large_data)
238 self.assertEqual(N, written)
239
240 wio.flush()
241 write_finished = True
242 t.join()
243
244 self.assertIsNone(error)
245 self.assertEqual(N, sum(len(x) for x in read_results))
246 finally:
247 signal.alarm(0)
248 write_finished = True
249 os.close(w)

Calls 9

joinMethod · 0.95
assertIsNoneMethod · 0.80
import_moduleMethod · 0.45
pipeMethod · 0.45
openMethod · 0.45
writeMethod · 0.45
assertEqualMethod · 0.45
flushMethod · 0.45
closeMethod · 0.45

Tested by

no test coverage detected