@@ -401,10 +401,10 @@ def self.read_string_nonblock(io, count, exception)
401
401
# by IO#sysread
402
402
403
403
def self . read_string_native ( io , length )
404
- fd = io . fileno
405
404
buffer = Primitive . io_thread_buffer_allocate ( length )
406
405
begin
407
- bytes_read = Truffle ::POSIX . read ( fd , buffer , length )
406
+ bytes_read = execute_posix_read ( io , buffer , length )
407
+
408
408
if bytes_read < 0
409
409
bytes_read , errno = bytes_read , Errno . errno
410
410
elsif bytes_read == 0 # EOF
@@ -425,11 +425,62 @@ def self.read_string_native(io, length)
425
425
end
426
426
end
427
427
428
- def self . read_to_buffer_native ( io , length )
428
+ def self . execute_posix_read ( io , buffer , length )
429
+ fd = io . fileno
430
+ return Truffle ::POSIX . read ( fd , buffer , length ) unless io . timeout
431
+
432
+ deadline = Process . clock_gettime ( Process ::CLOCK_MONOTONIC ) + io . timeout
433
+
434
+ loop do
435
+ current_timeout = deadline - Process . clock_gettime ( Process ::CLOCK_MONOTONIC )
436
+ raise IO ::TimeoutError if current_timeout < 0
437
+
438
+ poll_result = Truffle ::IOOperations . poll ( io , Truffle ::IOOperations ::POLLIN , current_timeout )
439
+ if poll_result == 0
440
+ raise IO ::TimeoutError
441
+ elsif poll_result == -1
442
+ Errno . handle_errno ( Errno . errno )
443
+ end
444
+
445
+ if ( bytes_read = Truffle ::POSIX . read ( fd , buffer , length ) ) == -1
446
+ continue if Errno . errno == Errno ::EAGAIN
447
+ break
448
+ end
449
+
450
+ return bytes_read
451
+ end
452
+ end
453
+
454
+ def self . execute_posix_write ( io , buffer , length )
429
455
fd = io . fileno
456
+ return Truffle ::POSIX . write ( fd , buffer , length ) unless io . timeout
457
+
458
+ deadline = Process . clock_gettime ( Process ::CLOCK_MONOTONIC ) + io . timeout
459
+
460
+ loop do
461
+ current_timeout = deadline - Process . clock_gettime ( Process ::CLOCK_MONOTONIC )
462
+ raise IO ::TimeoutError if current_timeout < 0
463
+
464
+ poll_result = Truffle ::IOOperations . poll ( io , Truffle ::IOOperations ::POLLOUT , current_timeout )
465
+ if poll_result == 0
466
+ raise IO ::TimeoutError
467
+ elsif poll_result == -1
468
+ Errno . handle_errno ( Errno . errno )
469
+ end
470
+
471
+ if ( bytes_written = Truffle ::POSIX . write ( fd , buffer , length ) ) == -1
472
+ continue if Errno . errno == Errno ::EAGAIN
473
+ break
474
+ end
475
+
476
+ return bytes_written
477
+ end
478
+ end
479
+
480
+ def self . read_to_buffer_native ( io , length )
430
481
buffer = Primitive . io_thread_buffer_allocate ( length )
431
482
begin
432
- bytes_read = Truffle :: POSIX . read ( fd , buffer , length )
483
+ bytes_read = execute_posix_read ( io , buffer , length )
433
484
if bytes_read < 0
434
485
bytes_read , errno = bytes_read , Errno . errno
435
486
elsif bytes_read == 0 # EOF
@@ -495,7 +546,7 @@ def self.write_string_native(io, string, continue_on_eagain)
495
546
496
547
written = 0
497
548
while written < length
498
- ret = Truffle :: POSIX . write ( fd , buffer + written , length - written )
549
+ ret = execute_posix_write ( io , buffer + written , length - written )
499
550
if ret < 0
500
551
errno = Errno . errno
501
552
if errno == EAGAIN_ERRNO
@@ -540,12 +591,11 @@ def self.write_string_polyglot(io, string, continue_on_eagain)
540
591
# #write_string_nonblock_polylgot) is called by IO#write_nonblock
541
592
542
593
def self . write_string_nonblock_native ( io , string )
543
- fd = io . fileno
544
594
length = string . bytesize
545
595
buffer = Primitive . io_thread_buffer_allocate ( length )
546
596
begin
547
597
buffer . write_bytes string
548
- written = Truffle :: POSIX . write ( fd , buffer , length )
598
+ written = execute_posix_write ( io , buffer , length )
549
599
550
600
if written < 0
551
601
errno = Errno . errno
0 commit comments