Skip to content

Commit 28e4d17

Browse files
committed
fix os.read to check signals
1 parent 339f0e7 commit 28e4d17

File tree

5 files changed

+40
-25
lines changed

5 files changed

+40
-25
lines changed

Lib/test/test_descr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4961,7 +4961,6 @@ class OverrideBoth(OverrideNew, OverrideInit):
49614961
self.assertRaises(TypeError, case, 1, 2, 3)
49624962
self.assertRaises(TypeError, case, 1, 2, foo=3)
49634963

4964-
@unittest.expectedFailure # TODO: RUSTPYTHON
49654964
def test_subclassing_does_not_duplicate_dict_descriptors(self):
49664965
class Base:
49674966
pass

Lib/test/test_file_eintr.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ def _test_reading(self, data_to_write, read_and_verify_code):
152152
'"got data %r\\nexpected %r" % (got, expected))'
153153
)
154154

155-
@unittest.expectedFailure # TODO: RUSTPYTHON
156155
def test_readline(self):
157156
"""readline() must handle signals and not lose data."""
158157
self._test_reading(
@@ -161,7 +160,6 @@ def test_readline(self):
161160
read_method_name='readline',
162161
expected=b'hello, world!\n'))
163162

164-
@unittest.expectedFailure # TODO: RUSTPYTHON
165163
def test_readlines(self):
166164
"""readlines() must handle signals and not lose data."""
167165
self._test_reading(
@@ -170,7 +168,6 @@ def test_readlines(self):
170168
read_method_name='readlines',
171169
expected=[b'hello\n', b'world!\n']))
172170

173-
@unittest.expectedFailure # TODO: RUSTPYTHON
174171
def test_readall(self):
175172
"""readall() must handle signals and not lose data."""
176173
self._test_reading(
@@ -189,6 +186,19 @@ def test_readall(self):
189186
class CTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase):
190187
modname = '_io'
191188

189+
# TODO: RUSTPYTHON - _io module uses _pyio internally, signal handling differs
190+
@unittest.expectedFailure
191+
def test_readline(self):
192+
super().test_readline()
193+
194+
@unittest.expectedFailure
195+
def test_readlines(self):
196+
super().test_readlines()
197+
198+
@unittest.expectedFailure
199+
def test_readall(self):
200+
super().test_readall()
201+
192202
class PyTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase):
193203
modname = '_pyio'
194204

@@ -200,7 +210,6 @@ def _generate_infile_setup_code(self):
200210
'assert isinstance(infile, io.BufferedReader)' %
201211
self.modname)
202212

203-
@unittest.expectedFailure # TODO: RUSTPYTHON
204213
def test_readall(self):
205214
"""BufferedReader.read() must handle signals and not lose data."""
206215
self._test_reading(
@@ -212,6 +221,19 @@ def test_readall(self):
212221
class CTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase):
213222
modname = '_io'
214223

224+
# TODO: RUSTPYTHON - _io module uses _pyio internally, signal handling differs
225+
@unittest.expectedFailure
226+
def test_readline(self):
227+
super().test_readline()
228+
229+
@unittest.expectedFailure
230+
def test_readlines(self):
231+
super().test_readlines()
232+
233+
@unittest.expectedFailure
234+
def test_readall(self):
235+
super().test_readall()
236+
215237
class PyTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase):
216238
modname = '_pyio'
217239

@@ -224,7 +246,6 @@ def _generate_infile_setup_code(self):
224246
'assert isinstance(infile, io.TextIOWrapper)' %
225247
self.modname)
226248

227-
@unittest.expectedFailure # TODO: RUSTPYTHON
228249
def test_readline(self):
229250
"""readline() must handle signals and not lose data."""
230251
self._test_reading(
@@ -233,7 +254,6 @@ def test_readline(self):
233254
read_method_name='readline',
234255
expected='hello, world!\n'))
235256

236-
@unittest.expectedFailure # TODO: RUSTPYTHON
237257
def test_readlines(self):
238258
"""readlines() must handle signals and not lose data."""
239259
self._test_reading(
@@ -242,7 +262,6 @@ def test_readlines(self):
242262
read_method_name='readlines',
243263
expected=['hello\n', 'world!\n']))
244264

245-
@unittest.expectedFailure # TODO: RUSTPYTHON
246265
def test_readall(self):
247266
"""read() must handle signals and not lose data."""
248267
self._test_reading(

Lib/test/test_signal.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -761,17 +761,13 @@ def handler(signum, frame):
761761
% (exitcode, stdout))
762762
return (exitcode == 3)
763763

764-
# TODO: RUSTPYTHON
765-
@unittest.expectedFailure
766764
def test_without_siginterrupt(self):
767765
# If a signal handler is installed and siginterrupt is not called
768766
# at all, when that signal arrives, it interrupts a syscall that's in
769767
# progress.
770768
interrupted = self.readpipe_interrupted(None)
771769
self.assertTrue(interrupted)
772770

773-
# TODO: RUSTPYTHON
774-
@unittest.expectedFailure
775771
def test_siginterrupt_on(self):
776772
# If a signal handler is installed and siginterrupt is called with
777773
# a true value for the second argument, when that signal arrives, it

Lib/test/test_socket.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,8 +2052,6 @@ def test_socket_fileno_requires_socket_fd(self):
20522052
fileno=afile.fileno())
20532053
self.assertEqual(cm.exception.errno, errno.ENOTSOCK)
20542054

2055-
# TODO: RUSTPYTHON
2056-
@unittest.expectedFailure
20572055
def test_addressfamily_enum(self):
20582056
import _socket, enum
20592057
CheckedAddressFamily = enum._old_convert_(
@@ -2063,8 +2061,6 @@ def test_addressfamily_enum(self):
20632061
)
20642062
enum._test_simple_enum(CheckedAddressFamily, socket.AddressFamily)
20652063

2066-
# TODO: RUSTPYTHON
2067-
@unittest.expectedFailure
20682064
def test_socketkind_enum(self):
20692065
import _socket, enum
20702066
CheckedSocketKind = enum._old_convert_(
@@ -2074,8 +2070,6 @@ def test_socketkind_enum(self):
20742070
)
20752071
enum._test_simple_enum(CheckedSocketKind, socket.SocketKind)
20762072

2077-
# TODO: RUSTPYTHON
2078-
@unittest.expectedFailure
20792073
def test_msgflag_enum(self):
20802074
import _socket, enum
20812075
CheckedMsgFlag = enum._old_convert_(
@@ -2085,8 +2079,6 @@ def test_msgflag_enum(self):
20852079
)
20862080
enum._test_simple_enum(CheckedMsgFlag, socket.MsgFlag)
20872081

2088-
# TODO: RUSTPYTHON
2089-
@unittest.expectedFailure
20902082
def test_addressinfo_enum(self):
20912083
import _socket, enum
20922084
CheckedAddressInfo = enum._old_convert_(

crates/vm/src/stdlib/os.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,21 @@ pub(super) mod _os {
274274
}
275275

276276
#[pyfunction]
277-
fn read(fd: crt_fd::Borrowed<'_>, n: usize, vm: &VirtualMachine) -> io::Result<PyBytesRef> {
277+
fn read(fd: crt_fd::Borrowed<'_>, n: usize, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
278278
let mut buffer = vec![0u8; n];
279-
let n = crt_fd::read(fd, &mut buffer)?;
280-
buffer.truncate(n);
281-
282-
Ok(vm.ctx.new_bytes(buffer))
279+
loop {
280+
match crt_fd::read(fd, &mut buffer) {
281+
Ok(n) => {
282+
buffer.truncate(n);
283+
return Ok(vm.ctx.new_bytes(buffer));
284+
}
285+
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
286+
vm.check_signals()?;
287+
continue;
288+
}
289+
Err(e) => return Err(e.into_pyexception(vm)),
290+
}
291+
}
283292
}
284293

285294
#[pyfunction]

0 commit comments

Comments
 (0)