uringmachine 0.19.1 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +3 -4
- data/CHANGELOG.md +32 -1
- data/TODO.md +0 -39
- data/examples/bm_fileno.rb +33 -0
- data/examples/bm_mutex.rb +85 -0
- data/examples/bm_mutex_single.rb +33 -0
- data/examples/bm_queue.rb +29 -29
- data/examples/bm_send.rb +2 -5
- data/examples/bm_snooze.rb +20 -42
- data/examples/bm_write.rb +4 -1
- data/examples/fiber_scheduler_demo.rb +15 -51
- data/examples/fiber_scheduler_fork.rb +24 -0
- data/examples/nc_ssl.rb +71 -0
- data/ext/um/extconf.rb +5 -15
- data/ext/um/um.c +310 -74
- data/ext/um/um.h +66 -29
- data/ext/um/um_async_op.c +1 -1
- data/ext/um/um_async_op_class.c +2 -2
- data/ext/um/um_buffer.c +1 -1
- data/ext/um/um_class.c +178 -31
- data/ext/um/um_const.c +51 -3
- data/ext/um/um_mutex_class.c +1 -1
- data/ext/um/um_op.c +37 -0
- data/ext/um/um_queue_class.c +1 -1
- data/ext/um/um_stream.c +5 -5
- data/ext/um/um_stream_class.c +3 -0
- data/ext/um/um_sync.c +28 -39
- data/ext/um/um_utils.c +59 -19
- data/grant-2025/journal.md +353 -0
- data/grant-2025/tasks.md +135 -0
- data/lib/uringmachine/fiber_scheduler.rb +316 -57
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +6 -0
- data/test/test_fiber_scheduler.rb +640 -0
- data/test/test_stream.rb +2 -2
- data/test/test_um.rb +722 -54
- data/uringmachine.gemspec +5 -5
- data/vendor/liburing/.github/workflows/ci.yml +94 -1
- data/vendor/liburing/.github/workflows/test_build.c +9 -0
- data/vendor/liburing/configure +27 -0
- data/vendor/liburing/examples/Makefile +6 -0
- data/vendor/liburing/examples/helpers.c +8 -0
- data/vendor/liburing/examples/helpers.h +5 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +9 -3
- data/vendor/liburing/src/include/liburing/barrier.h +11 -5
- data/vendor/liburing/src/include/liburing/io_uring/query.h +41 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +51 -0
- data/vendor/liburing/src/include/liburing/sanitize.h +16 -4
- data/vendor/liburing/src/include/liburing.h +458 -121
- data/vendor/liburing/src/liburing-ffi.map +16 -0
- data/vendor/liburing/src/liburing.map +8 -0
- data/vendor/liburing/src/sanitize.c +4 -1
- data/vendor/liburing/src/setup.c +7 -4
- data/vendor/liburing/test/232c93d07b74.c +4 -16
- data/vendor/liburing/test/Makefile +15 -1
- data/vendor/liburing/test/accept.c +2 -13
- data/vendor/liburing/test/bind-listen.c +175 -13
- data/vendor/liburing/test/conn-unreach.c +132 -0
- data/vendor/liburing/test/fd-pass.c +32 -7
- data/vendor/liburing/test/fdinfo.c +39 -12
- data/vendor/liburing/test/fifo-futex-poll.c +114 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +1 -12
- data/vendor/liburing/test/futex.c +1 -1
- data/vendor/liburing/test/helpers.c +99 -2
- data/vendor/liburing/test/helpers.h +9 -0
- data/vendor/liburing/test/io_uring_passthrough.c +6 -12
- data/vendor/liburing/test/mock_file.c +379 -0
- data/vendor/liburing/test/mock_file.h +47 -0
- data/vendor/liburing/test/nop.c +2 -2
- data/vendor/liburing/test/nop32-overflow.c +150 -0
- data/vendor/liburing/test/nop32.c +126 -0
- data/vendor/liburing/test/pipe.c +166 -0
- data/vendor/liburing/test/poll-race-mshot.c +13 -1
- data/vendor/liburing/test/read-write.c +4 -4
- data/vendor/liburing/test/recv-mshot-fair.c +81 -34
- data/vendor/liburing/test/recvsend_bundle.c +1 -1
- data/vendor/liburing/test/resize-rings.c +2 -0
- data/vendor/liburing/test/ring-query.c +322 -0
- data/vendor/liburing/test/ringbuf-loop.c +87 -0
- data/vendor/liburing/test/ringbuf-read.c +4 -4
- data/vendor/liburing/test/runtests.sh +2 -2
- data/vendor/liburing/test/send-zerocopy.c +43 -5
- data/vendor/liburing/test/send_recv.c +103 -32
- data/vendor/liburing/test/shutdown.c +2 -12
- data/vendor/liburing/test/socket-nb.c +3 -14
- data/vendor/liburing/test/socket-rw-eagain.c +2 -12
- data/vendor/liburing/test/socket-rw-offset.c +2 -12
- data/vendor/liburing/test/socket-rw.c +2 -12
- data/vendor/liburing/test/sqe-mixed-bad-wrap.c +87 -0
- data/vendor/liburing/test/sqe-mixed-nop.c +82 -0
- data/vendor/liburing/test/sqe-mixed-uring_cmd.c +153 -0
- data/vendor/liburing/test/timestamp.c +56 -19
- data/vendor/liburing/test/vec-regbuf.c +2 -4
- data/vendor/liburing/test/wq-aff.c +7 -0
- metadata +37 -15
data/test/test_um.rb
CHANGED
|
@@ -11,6 +11,80 @@ class UringMachineTest < Minitest::Test
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
class EntriesTest < Minitest::Test
|
|
15
|
+
def test_default_entries
|
|
16
|
+
m = UM.new
|
|
17
|
+
assert_equal 4096, m.entries
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_custom_entries_value
|
|
21
|
+
m = UM.new(13)
|
|
22
|
+
assert_equal 13, m.entries
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class SQPOLLTest < Minitest::Test
|
|
27
|
+
def test_sqpoll_timeout
|
|
28
|
+
m = UM.new(10, 0.05)
|
|
29
|
+
|
|
30
|
+
r, w = UM.pipe
|
|
31
|
+
|
|
32
|
+
buf = nil
|
|
33
|
+
t = Thread.new { buf = IO.new(r).readpartial(3) }
|
|
34
|
+
|
|
35
|
+
# let SQPOLL worker thread timeout
|
|
36
|
+
sleep(0.06)
|
|
37
|
+
|
|
38
|
+
# SQE is prepared but not submitted
|
|
39
|
+
m.write_async(w, 'foo')
|
|
40
|
+
|
|
41
|
+
# thread should timeout
|
|
42
|
+
ret = t.join(0.03)
|
|
43
|
+
assert_nil buf
|
|
44
|
+
ensure
|
|
45
|
+
t.kill rescue nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_sqpoll_timeout_with_submit
|
|
49
|
+
m = UM.new(10, 0.05)
|
|
50
|
+
|
|
51
|
+
r, w = UM.pipe
|
|
52
|
+
|
|
53
|
+
buf = nil
|
|
54
|
+
t = Thread.new { buf = IO.new(r).readpartial(3) }
|
|
55
|
+
|
|
56
|
+
# let SQPOLL worker thread timeout
|
|
57
|
+
sleep(0.06)
|
|
58
|
+
|
|
59
|
+
# SQE is prepared but not submitted
|
|
60
|
+
m.write_async(w, 'foo')
|
|
61
|
+
ret = m.submit
|
|
62
|
+
assert_equal 1, ret
|
|
63
|
+
|
|
64
|
+
# thread should timeout
|
|
65
|
+
ret = t.join(0.1)
|
|
66
|
+
assert_equal 'foo', buf
|
|
67
|
+
ensure
|
|
68
|
+
t.kill rescue nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class SubmitTest < UMBaseTest
|
|
73
|
+
def test_submit
|
|
74
|
+
_r, w = UM.pipe
|
|
75
|
+
|
|
76
|
+
machine.write_async(w, 'foo')
|
|
77
|
+
machine.write_async(w, 'bar')
|
|
78
|
+
machine.write_async(w, 'baz')
|
|
79
|
+
|
|
80
|
+
assert_equal 3, machine.pending_count
|
|
81
|
+
assert_equal 3, machine.submit
|
|
82
|
+
assert_equal 0, machine.submit
|
|
83
|
+
machine.snooze
|
|
84
|
+
assert_equal 0, machine.pending_count
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
14
88
|
class SpinTest < UMBaseTest
|
|
15
89
|
def test_spin
|
|
16
90
|
x = nil
|
|
@@ -164,7 +238,7 @@ class ScheduleTest < UMBaseTest
|
|
|
164
238
|
}
|
|
165
239
|
machine.join(*fs)
|
|
166
240
|
ensure
|
|
167
|
-
GC.stress = false
|
|
241
|
+
GC.stress = false
|
|
168
242
|
end
|
|
169
243
|
|
|
170
244
|
def test_timeout_with_raising_block
|
|
@@ -327,16 +401,36 @@ class PeriodicallyTest < UMBaseTest
|
|
|
327
401
|
rescue Cancel
|
|
328
402
|
cancel = 1
|
|
329
403
|
end
|
|
330
|
-
|
|
331
|
-
assert_equal 0, machine.pending_count
|
|
404
|
+
assert_equal 1, cancel
|
|
332
405
|
t1 = monotonic_clock
|
|
333
406
|
assert_in_range 0.05..0.08, t1 - t0
|
|
334
407
|
assert_in_range 4..6, count
|
|
335
|
-
assert_equal 1, cancel
|
|
336
408
|
|
|
337
409
|
end
|
|
338
410
|
end
|
|
339
411
|
|
|
412
|
+
class StatsTest < UMBaseTest
|
|
413
|
+
def test_op_counts
|
|
414
|
+
_r, w = IO.pipe
|
|
415
|
+
|
|
416
|
+
assert_equal 0, machine.pending_count
|
|
417
|
+
assert_equal 0, machine.total_op_count
|
|
418
|
+
machine.write_async(w.fileno, 'foo')
|
|
419
|
+
assert_equal 1, machine.pending_count
|
|
420
|
+
assert_equal 1, machine.total_op_count
|
|
421
|
+
machine.snooze
|
|
422
|
+
assert_equal 0, machine.pending_count
|
|
423
|
+
assert_equal 1, machine.total_op_count
|
|
424
|
+
|
|
425
|
+
machine.write_async(w.fileno, 'foo')
|
|
426
|
+
assert_equal 1, machine.pending_count
|
|
427
|
+
assert_equal 2, machine.total_op_count
|
|
428
|
+
machine.snooze
|
|
429
|
+
assert_equal 0, machine.pending_count
|
|
430
|
+
assert_equal 2, machine.total_op_count
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
340
434
|
class ReadTest < UMBaseTest
|
|
341
435
|
def test_read
|
|
342
436
|
r, w = IO.pipe
|
|
@@ -419,6 +513,64 @@ class ReadTest < UMBaseTest
|
|
|
419
513
|
assert_equal 3, result
|
|
420
514
|
assert_equal 'baz', sio.read
|
|
421
515
|
end
|
|
516
|
+
|
|
517
|
+
def test_read_io_buffer
|
|
518
|
+
r, w = UM.pipe
|
|
519
|
+
machine.write(w, 'foobar')
|
|
520
|
+
|
|
521
|
+
read_buffer = IO::Buffer.new(3)
|
|
522
|
+
res = machine.read(r, read_buffer, 3)
|
|
523
|
+
assert_equal 3, res
|
|
524
|
+
assert_equal 'foo', read_buffer.get_string(0, 3)
|
|
525
|
+
|
|
526
|
+
machine.close(w)
|
|
527
|
+
|
|
528
|
+
res = machine.read(r, read_buffer)
|
|
529
|
+
assert_equal 3, res
|
|
530
|
+
assert_equal 'bar', read_buffer.get_string(0, 3)
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def test_read_io_buffer_resize
|
|
534
|
+
r, w = UM.pipe
|
|
535
|
+
machine.write(w, 'foobar')
|
|
536
|
+
machine.close(w)
|
|
537
|
+
|
|
538
|
+
read_buffer = IO::Buffer.new(3)
|
|
539
|
+
res = machine.read(r, read_buffer, 6)
|
|
540
|
+
assert_equal 6, res
|
|
541
|
+
assert_equal 6, read_buffer.size
|
|
542
|
+
assert_equal 'foobar', read_buffer.get_string(0, res)
|
|
543
|
+
|
|
544
|
+
r, w = UM.pipe
|
|
545
|
+
machine.write(w, 'foobar')
|
|
546
|
+
machine.close(w)
|
|
547
|
+
|
|
548
|
+
read_buffer = IO::Buffer.new(3)
|
|
549
|
+
res = machine.read(r, read_buffer, 128, -1)
|
|
550
|
+
assert_equal 6, res
|
|
551
|
+
assert_equal 131, read_buffer.size
|
|
552
|
+
assert_equal 'foobar', read_buffer.get_string(3, res)
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def test_read_invalid_buffer
|
|
556
|
+
r, _w = UM.pipe
|
|
557
|
+
assert_raises(UM::Error) {
|
|
558
|
+
machine.read(r, [])
|
|
559
|
+
}
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def test_read_with_file_offset
|
|
563
|
+
fn = "/tmp/#{SecureRandom.hex}"
|
|
564
|
+
IO.write(fn, 'foobar')
|
|
565
|
+
|
|
566
|
+
fd = machine.open(fn, UM::O_RDONLY)
|
|
567
|
+
buffer = +''
|
|
568
|
+
result = machine.read(fd, buffer, 100, 0, 2)
|
|
569
|
+
assert_equal 4, result
|
|
570
|
+
assert_equal 'obar', buffer
|
|
571
|
+
ensure
|
|
572
|
+
machine.close(fd)
|
|
573
|
+
end
|
|
422
574
|
end
|
|
423
575
|
|
|
424
576
|
class ReadEachTest < UMBaseTest
|
|
@@ -569,11 +721,13 @@ class WriteTest < UMBaseTest
|
|
|
569
721
|
r, w = IO.pipe
|
|
570
722
|
|
|
571
723
|
assert_equal 0, machine.pending_count
|
|
572
|
-
machine.write(w.fileno, 'foo')
|
|
724
|
+
res = machine.write(w.fileno, 'foo')
|
|
725
|
+
assert_equal 3, res
|
|
573
726
|
assert_equal 0, machine.pending_count
|
|
574
727
|
assert_equal 'foo', r.readpartial(3)
|
|
575
728
|
|
|
576
|
-
machine.write(w.fileno, 'bar', 2)
|
|
729
|
+
res = machine.write(w.fileno, 'bar', 2)
|
|
730
|
+
assert_equal 2, res
|
|
577
731
|
assert_equal 'ba', r.readpartial(3)
|
|
578
732
|
end
|
|
579
733
|
|
|
@@ -586,6 +740,85 @@ class WriteTest < UMBaseTest
|
|
|
586
740
|
end
|
|
587
741
|
assert_equal 0, machine.pending_count
|
|
588
742
|
end
|
|
743
|
+
|
|
744
|
+
def test_write_zero_length
|
|
745
|
+
r, w = IO.pipe
|
|
746
|
+
|
|
747
|
+
res = machine.write(w.fileno, '')
|
|
748
|
+
assert_equal 0, res
|
|
749
|
+
|
|
750
|
+
res = machine.write(w.fileno, 'bar', 0)
|
|
751
|
+
assert_equal 0, res
|
|
752
|
+
|
|
753
|
+
buf = IO::Buffer.new(3)
|
|
754
|
+
buf.set_string('baz')
|
|
755
|
+
res = machine.write(w.fileno, buf, 0, 0)
|
|
756
|
+
assert_equal 0, res
|
|
757
|
+
|
|
758
|
+
w.close
|
|
759
|
+
assert_equal '', r.read
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
def test_write_io_buffer
|
|
763
|
+
r, w = UM.pipe
|
|
764
|
+
|
|
765
|
+
msg = 'Hello world'
|
|
766
|
+
write_buffer = IO::Buffer.new(msg.bytesize)
|
|
767
|
+
write_buffer.set_string(msg, 0)
|
|
768
|
+
|
|
769
|
+
machine.write(w, write_buffer)
|
|
770
|
+
machine.close(w)
|
|
771
|
+
|
|
772
|
+
str = +''
|
|
773
|
+
machine.read(r, str, 8192)
|
|
774
|
+
assert_equal msg, str
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
def test_write_io_buffer_with_len
|
|
778
|
+
r, w = UM.pipe
|
|
779
|
+
msg = 'Hello world'
|
|
780
|
+
write_buffer = IO::Buffer.new(msg.bytesize)
|
|
781
|
+
write_buffer.set_string(msg)
|
|
782
|
+
|
|
783
|
+
machine.write(w, write_buffer, 5)
|
|
784
|
+
machine.close(w)
|
|
785
|
+
|
|
786
|
+
str = +''
|
|
787
|
+
machine.read(r, str, 8192)
|
|
788
|
+
assert_equal 'Hello', str
|
|
789
|
+
|
|
790
|
+
r, w = UM.pipe
|
|
791
|
+
msg = 'Hello world'
|
|
792
|
+
write_buffer = IO::Buffer.new(msg.bytesize)
|
|
793
|
+
write_buffer.set_string(msg)
|
|
794
|
+
|
|
795
|
+
machine.write(w, write_buffer, -1)
|
|
796
|
+
machine.close(w)
|
|
797
|
+
|
|
798
|
+
str = +''
|
|
799
|
+
machine.read(r, str, 8192)
|
|
800
|
+
assert_equal 'Hello world', str
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
def test_write_invalid_buffer
|
|
804
|
+
_r, w = UM.pipe
|
|
805
|
+
assert_raises(UM::Error) {
|
|
806
|
+
machine.write(w, [])
|
|
807
|
+
}
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
def test_write_with_file_offset
|
|
811
|
+
fn = "/tmp/#{SecureRandom.hex}"
|
|
812
|
+
IO.write(fn, 'foobar')
|
|
813
|
+
|
|
814
|
+
fd = machine.open(fn, UM::O_WRONLY)
|
|
815
|
+
result = machine.write(fd, 'baz', -1, 2)
|
|
816
|
+
assert_equal 3, result
|
|
817
|
+
assert_equal 'fobazr', IO.read(fn)
|
|
818
|
+
ensure
|
|
819
|
+
machine.close(fd)
|
|
820
|
+
end
|
|
821
|
+
|
|
589
822
|
end
|
|
590
823
|
|
|
591
824
|
class WriteAsyncTest < UMBaseTest
|
|
@@ -596,7 +829,7 @@ class WriteAsyncTest < UMBaseTest
|
|
|
596
829
|
machine.write_async(w.fileno, 'foo')
|
|
597
830
|
assert_equal 1, machine.pending_count
|
|
598
831
|
|
|
599
|
-
machine.snooze
|
|
832
|
+
machine.snooze while machine.pending_count > 0
|
|
600
833
|
assert_equal 0, machine.pending_count
|
|
601
834
|
assert_equal 'foo', r.readpartial(3)
|
|
602
835
|
end
|
|
@@ -612,7 +845,7 @@ class WriteAsyncTest < UMBaseTest
|
|
|
612
845
|
GC.start
|
|
613
846
|
assert_equal 1, machine.pending_count
|
|
614
847
|
|
|
615
|
-
machine.snooze
|
|
848
|
+
machine.snooze while machine.pending_count > 0
|
|
616
849
|
assert_equal 0, machine.pending_count
|
|
617
850
|
assert_equal "foo#{123}#{'bar' * 48}", r.readpartial(len)
|
|
618
851
|
end
|
|
@@ -626,6 +859,54 @@ class WriteAsyncTest < UMBaseTest
|
|
|
626
859
|
machine.snooze
|
|
627
860
|
assert_equal 0, machine.pending_count
|
|
628
861
|
end
|
|
862
|
+
|
|
863
|
+
def test_write_async_io_buffer
|
|
864
|
+
r, w = UM.pipe
|
|
865
|
+
|
|
866
|
+
msg = 'Hello world'
|
|
867
|
+
write_buffer = IO::Buffer.new(msg.bytesize)
|
|
868
|
+
write_buffer.set_string(msg)
|
|
869
|
+
|
|
870
|
+
machine.write_async(w, write_buffer)
|
|
871
|
+
machine.snooze while machine.pending_count > 0
|
|
872
|
+
machine.close(w)
|
|
873
|
+
|
|
874
|
+
str = +''
|
|
875
|
+
machine.read(r, str, 8192)
|
|
876
|
+
assert_equal msg, str
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
def test_write_async_invalid_buffer
|
|
880
|
+
_r, w = UM.pipe
|
|
881
|
+
|
|
882
|
+
assert_raises(UM::Error) { machine.write_async(w, []) }
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
def test_write_async_with_len
|
|
886
|
+
r, w = IO.pipe
|
|
887
|
+
|
|
888
|
+
assert_equal 0, machine.pending_count
|
|
889
|
+
machine.write_async(w.fileno, 'foobar', 4)
|
|
890
|
+
|
|
891
|
+
assert_equal 1, machine.pending_count
|
|
892
|
+
machine.snooze while machine.pending_count > 0
|
|
893
|
+
assert_equal 0, machine.pending_count
|
|
894
|
+
assert_equal 'foob', r.readpartial(6)
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
def test_write_async_with_file_offset
|
|
898
|
+
fn = "/tmp/#{SecureRandom.hex}"
|
|
899
|
+
IO.write(fn, 'foobar')
|
|
900
|
+
|
|
901
|
+
fd = machine.open(fn, UM::O_WRONLY)
|
|
902
|
+
machine.write_async(fd, 'baz', -1, 2)
|
|
903
|
+
|
|
904
|
+
assert_equal 1, machine.pending_count
|
|
905
|
+
machine.snooze while machine.pending_count > 0
|
|
906
|
+
assert_equal 'fobazr', IO.read(fn)
|
|
907
|
+
ensure
|
|
908
|
+
machine.close(fd)
|
|
909
|
+
end
|
|
629
910
|
end
|
|
630
911
|
|
|
631
912
|
class CloseTest < UMBaseTest
|
|
@@ -643,7 +924,7 @@ class CloseTest < UMBaseTest
|
|
|
643
924
|
end
|
|
644
925
|
|
|
645
926
|
def test_close_bad_fd
|
|
646
|
-
|
|
927
|
+
_r, w = IO.pipe
|
|
647
928
|
machine.close(w.fileno)
|
|
648
929
|
|
|
649
930
|
assert_raises(Errno::EBADF) { machine.close(w.fileno) }
|
|
@@ -902,6 +1183,78 @@ class SendTest < UMBaseTest
|
|
|
902
1183
|
ensure
|
|
903
1184
|
t&.kill
|
|
904
1185
|
end
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
def test_send_io_buffer
|
|
1189
|
+
@port = assign_port
|
|
1190
|
+
@server = TCPServer.open('127.0.0.1', @port)
|
|
1191
|
+
|
|
1192
|
+
t = Thread.new do
|
|
1193
|
+
conn = @server.accept
|
|
1194
|
+
str = conn.readpartial(42)
|
|
1195
|
+
conn.write("You said: #{str} (#{str.bytesize})")
|
|
1196
|
+
sleep
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
|
1200
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1201
|
+
assert_equal 0, res
|
|
1202
|
+
|
|
1203
|
+
buffer = IO::Buffer.new(6)
|
|
1204
|
+
buffer.set_string('foobar')
|
|
1205
|
+
res = machine.send(fd, buffer, 6, 0)
|
|
1206
|
+
assert_equal 6, res
|
|
1207
|
+
|
|
1208
|
+
buf = +''
|
|
1209
|
+
res = machine.read(fd, buf, 42)
|
|
1210
|
+
assert_equal 20, res
|
|
1211
|
+
assert_equal 'You said: foobar (6)', buf
|
|
1212
|
+
ensure
|
|
1213
|
+
t&.kill
|
|
1214
|
+
@server&.close
|
|
1215
|
+
end
|
|
1216
|
+
|
|
1217
|
+
def test_send_io_buffer_negative_len
|
|
1218
|
+
t = Thread.new do
|
|
1219
|
+
conn = @server.accept
|
|
1220
|
+
str = conn.readpartial(42)
|
|
1221
|
+
conn.write("You said: #{str} (#{str.bytesize})")
|
|
1222
|
+
sleep
|
|
1223
|
+
end
|
|
1224
|
+
|
|
1225
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
|
1226
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1227
|
+
assert_equal 0, res
|
|
1228
|
+
|
|
1229
|
+
buffer = IO::Buffer.new(6)
|
|
1230
|
+
buffer.set_string('foobar')
|
|
1231
|
+
res = machine.send(fd, buffer, -1, 0)
|
|
1232
|
+
assert_equal 6, res
|
|
1233
|
+
|
|
1234
|
+
buf = +''
|
|
1235
|
+
res = machine.read(fd, buf, 42)
|
|
1236
|
+
assert_equal 20, res
|
|
1237
|
+
assert_equal 'You said: foobar (6)', buf
|
|
1238
|
+
ensure
|
|
1239
|
+
t&.kill
|
|
1240
|
+
end
|
|
1241
|
+
|
|
1242
|
+
def test_send_invalid_buffer
|
|
1243
|
+
t = Thread.new do
|
|
1244
|
+
conn = @server.accept
|
|
1245
|
+
str = conn.readpartial(42)
|
|
1246
|
+
conn.write("You said: #{str} (#{str.bytesize})")
|
|
1247
|
+
sleep
|
|
1248
|
+
end
|
|
1249
|
+
|
|
1250
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
|
1251
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1252
|
+
assert_equal 0, res
|
|
1253
|
+
|
|
1254
|
+
assert_raises(UM::Error) { machine.send(fd, [], -1, 0) }
|
|
1255
|
+
ensure
|
|
1256
|
+
t&.kill
|
|
1257
|
+
end
|
|
905
1258
|
end
|
|
906
1259
|
|
|
907
1260
|
class RecvTest < UMBaseTest
|
|
@@ -934,6 +1287,25 @@ class RecvTest < UMBaseTest
|
|
|
934
1287
|
ensure
|
|
935
1288
|
t&.kill
|
|
936
1289
|
end
|
|
1290
|
+
|
|
1291
|
+
def test_recv_io_buffer
|
|
1292
|
+
t = Thread.new do
|
|
1293
|
+
conn = @server.accept
|
|
1294
|
+
conn.write('foobar')
|
|
1295
|
+
sleep
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
|
1299
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1300
|
+
assert_equal 0, res
|
|
1301
|
+
|
|
1302
|
+
buf = IO::Buffer.new(12)
|
|
1303
|
+
res = machine.recv(fd, buf, 12, 0)
|
|
1304
|
+
assert_equal 6, res
|
|
1305
|
+
assert_equal 'foobar', buf.get_string(0, 6)
|
|
1306
|
+
ensure
|
|
1307
|
+
t&.kill
|
|
1308
|
+
end
|
|
937
1309
|
end
|
|
938
1310
|
|
|
939
1311
|
class RecvEachTest < UMBaseTest
|
|
@@ -1070,8 +1442,6 @@ end
|
|
|
1070
1442
|
|
|
1071
1443
|
class SynchronizeTest < UMBaseTest
|
|
1072
1444
|
def test_synchronize_single
|
|
1073
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1074
|
-
|
|
1075
1445
|
m = UM::Mutex.new
|
|
1076
1446
|
|
|
1077
1447
|
buf = []
|
|
@@ -1087,7 +1457,6 @@ class SynchronizeTest < UMBaseTest
|
|
|
1087
1457
|
end
|
|
1088
1458
|
|
|
1089
1459
|
def test_synchronize_pair
|
|
1090
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1091
1460
|
m = UM::Mutex.new
|
|
1092
1461
|
|
|
1093
1462
|
buf = []
|
|
@@ -1119,12 +1488,29 @@ class SynchronizeTest < UMBaseTest
|
|
|
1119
1488
|
assert_equal [11, 12, 13, 21, 22, 23], buf
|
|
1120
1489
|
assert_equal 0, machine.pending_count
|
|
1121
1490
|
end
|
|
1491
|
+
|
|
1492
|
+
def test_synchronize_multi
|
|
1493
|
+
mutex = UM::Mutex.new
|
|
1494
|
+
buf = []
|
|
1495
|
+
fibers = (1..8).map { |i|
|
|
1496
|
+
machine.spin do
|
|
1497
|
+
machine.synchronize(mutex) do
|
|
1498
|
+
buf << (i * 10) + 1
|
|
1499
|
+
machine.sleep(0.01)
|
|
1500
|
+
buf << (i * 10) + 2
|
|
1501
|
+
end
|
|
1502
|
+
machine.snooze
|
|
1503
|
+
buf << (i * 10) + 3
|
|
1504
|
+
end
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
machine.join(*fibers)
|
|
1508
|
+
assert_equal [11, 12, 21, 13, 22, 31, 23, 32, 41, 33, 42, 51, 43, 52, 61, 53, 62, 71, 63, 72, 81, 73, 82, 83], buf
|
|
1509
|
+
end
|
|
1122
1510
|
end
|
|
1123
1511
|
|
|
1124
1512
|
class QueueTest < UMBaseTest
|
|
1125
1513
|
def test_push_pop_1
|
|
1126
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1127
|
-
|
|
1128
1514
|
q = UM::Queue.new
|
|
1129
1515
|
assert_equal 0, q.count
|
|
1130
1516
|
machine.push(q, :foo)
|
|
@@ -1138,8 +1524,6 @@ class QueueTest < UMBaseTest
|
|
|
1138
1524
|
end
|
|
1139
1525
|
|
|
1140
1526
|
def test_push_pop_2
|
|
1141
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1142
|
-
|
|
1143
1527
|
q = UM::Queue.new
|
|
1144
1528
|
buf = []
|
|
1145
1529
|
|
|
@@ -1170,8 +1554,6 @@ class QueueTest < UMBaseTest
|
|
|
1170
1554
|
end
|
|
1171
1555
|
|
|
1172
1556
|
def test_push_pop_3
|
|
1173
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1174
|
-
|
|
1175
1557
|
q = UM::Queue.new
|
|
1176
1558
|
buf = []
|
|
1177
1559
|
|
|
@@ -1198,8 +1580,6 @@ class QueueTest < UMBaseTest
|
|
|
1198
1580
|
end
|
|
1199
1581
|
|
|
1200
1582
|
def test_push_pop_4
|
|
1201
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1202
|
-
|
|
1203
1583
|
q = UM::Queue.new
|
|
1204
1584
|
buf = []
|
|
1205
1585
|
|
|
@@ -1227,8 +1607,6 @@ class QueueTest < UMBaseTest
|
|
|
1227
1607
|
end
|
|
1228
1608
|
|
|
1229
1609
|
def test_push_shift_1
|
|
1230
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1231
|
-
|
|
1232
1610
|
q = UM::Queue.new
|
|
1233
1611
|
|
|
1234
1612
|
machine.push(q, :foo)
|
|
@@ -1241,8 +1619,6 @@ class QueueTest < UMBaseTest
|
|
|
1241
1619
|
end
|
|
1242
1620
|
|
|
1243
1621
|
def test_shift_shift_1
|
|
1244
|
-
skip if !machine.respond_to?(:synchronize)
|
|
1245
|
-
|
|
1246
1622
|
q = UM::Queue.new
|
|
1247
1623
|
|
|
1248
1624
|
machine.unshift(q, :foo)
|
|
@@ -1254,6 +1630,15 @@ class QueueTest < UMBaseTest
|
|
|
1254
1630
|
assert_equal :foo, machine.shift(q)
|
|
1255
1631
|
end
|
|
1256
1632
|
|
|
1633
|
+
def test_shift_exception_value
|
|
1634
|
+
q = UM::Queue.new
|
|
1635
|
+
machine.unshift(q, Exception.new("foo"))
|
|
1636
|
+
|
|
1637
|
+
e = machine.shift(q)
|
|
1638
|
+
assert_kind_of Exception, e
|
|
1639
|
+
assert_equal "foo", e.message
|
|
1640
|
+
end
|
|
1641
|
+
|
|
1257
1642
|
def test_cross_thread_push_shift
|
|
1258
1643
|
q = UM::Queue.new
|
|
1259
1644
|
|
|
@@ -1277,6 +1662,42 @@ class QueueTest < UMBaseTest
|
|
|
1277
1662
|
|
|
1278
1663
|
assert_equal [0, 1, 2], items
|
|
1279
1664
|
end
|
|
1665
|
+
|
|
1666
|
+
def test_cross_thread_cross_queue_comms
|
|
1667
|
+
worker_queue = UM::Queue.new
|
|
1668
|
+
|
|
1669
|
+
buf = []
|
|
1670
|
+
t1 = Thread.new {
|
|
1671
|
+
m = UM.new
|
|
1672
|
+
(1..10).each {
|
|
1673
|
+
q = UM::Queue.new
|
|
1674
|
+
m.push(worker_queue, [q, it])
|
|
1675
|
+
res = m.shift(q)
|
|
1676
|
+
buf << res
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
t2 = Thread.new {
|
|
1681
|
+
m = UM.new
|
|
1682
|
+
loop do
|
|
1683
|
+
q, v = m.shift(worker_queue)
|
|
1684
|
+
break if q == :STOP
|
|
1685
|
+
|
|
1686
|
+
res = v * 10
|
|
1687
|
+
m.push(q, res)
|
|
1688
|
+
end
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
t1.join
|
|
1692
|
+
q = UM::Queue.new
|
|
1693
|
+
machine.push(worker_queue, :STOP)
|
|
1694
|
+
t2.join
|
|
1695
|
+
|
|
1696
|
+
assert_equal (1..10).map { it * 10 }, buf
|
|
1697
|
+
ensure
|
|
1698
|
+
t1.kill rescue nil
|
|
1699
|
+
t2.kill rescue nil
|
|
1700
|
+
end
|
|
1280
1701
|
end
|
|
1281
1702
|
|
|
1282
1703
|
class OpenTest < UMBaseTest
|
|
@@ -1335,12 +1756,67 @@ class PipeTest < UMBaseTest
|
|
|
1335
1756
|
end
|
|
1336
1757
|
end
|
|
1337
1758
|
|
|
1759
|
+
class PidfdTest < UMBaseTest
|
|
1760
|
+
def test_pidfd_open
|
|
1761
|
+
pid = fork { exit 13 }
|
|
1762
|
+
fd = UM.pidfd_open(pid)
|
|
1763
|
+
assert_kind_of Integer, fd
|
|
1764
|
+
|
|
1765
|
+
pid2, status = machine.waitid(P_PIDFD, fd, UM::WEXITED)
|
|
1766
|
+
assert_equal pid, pid2
|
|
1767
|
+
assert_equal 13, status
|
|
1768
|
+
ensure
|
|
1769
|
+
machine.close(fd) rescue nil
|
|
1770
|
+
Process.wait(pid) rescue nil
|
|
1771
|
+
end
|
|
1772
|
+
|
|
1773
|
+
def test_pidfd_open_invalid_pid
|
|
1774
|
+
assert_raises(SystemCallError) { UM.pidfd_open(Process.pid + 1) }
|
|
1775
|
+
end
|
|
1776
|
+
|
|
1777
|
+
def test_pidfd_send_signal
|
|
1778
|
+
fd = UM.pidfd_open(Process.pid)
|
|
1779
|
+
buf = []
|
|
1780
|
+
trap('SIGUSR1') { buf << :SIGUSR1 }
|
|
1781
|
+
|
|
1782
|
+
ret = UM.pidfd_send_signal(fd, UM::SIGUSR1)
|
|
1783
|
+
assert_equal fd, ret
|
|
1784
|
+
sleep 0.01
|
|
1785
|
+
|
|
1786
|
+
assert_equal [:SIGUSR1], buf
|
|
1787
|
+
ensure
|
|
1788
|
+
machine.close(fd) rescue nil
|
|
1789
|
+
end
|
|
1790
|
+
|
|
1791
|
+
def test_pidfd_send_signal_test
|
|
1792
|
+
fd = UM.pidfd_open(Process.pid)
|
|
1793
|
+
buf = []
|
|
1794
|
+
trap('SIGUSR1') { buf << :SIGUSR1 }
|
|
1795
|
+
|
|
1796
|
+
ret = UM.pidfd_send_signal(fd, 0)
|
|
1797
|
+
assert_equal fd, ret
|
|
1798
|
+
sleep 0.01
|
|
1799
|
+
assert_equal [], buf
|
|
1800
|
+
|
|
1801
|
+
pid = fork { exit 13 }
|
|
1802
|
+
fd2 = UM.pidfd_open(pid)
|
|
1803
|
+
assert_kind_of Integer, fd2
|
|
1804
|
+
|
|
1805
|
+
Process.wait(pid)
|
|
1806
|
+
assert_raises(SystemCallError) { UM.pidfd_send_signal(fd2, 0) }
|
|
1807
|
+
ensure
|
|
1808
|
+
machine.close(fd) rescue nil
|
|
1809
|
+
machine.close(fd2) rescue nil
|
|
1810
|
+
Process.wait(pid) rescue nil
|
|
1811
|
+
end
|
|
1812
|
+
end
|
|
1813
|
+
|
|
1338
1814
|
class PollTest < UMBaseTest
|
|
1339
1815
|
def test_poll
|
|
1340
1816
|
rfd, wfd = UM.pipe
|
|
1341
1817
|
|
|
1342
1818
|
events = []
|
|
1343
|
-
|
|
1819
|
+
machine.spin do
|
|
1344
1820
|
events << :pre
|
|
1345
1821
|
events << machine.poll(rfd, UM::POLLIN)
|
|
1346
1822
|
events << :post
|
|
@@ -1366,38 +1842,160 @@ class PollTest < UMBaseTest
|
|
|
1366
1842
|
end
|
|
1367
1843
|
end
|
|
1368
1844
|
|
|
1369
|
-
class
|
|
1370
|
-
def
|
|
1371
|
-
|
|
1845
|
+
class SelectTest < UMBaseTest
|
|
1846
|
+
def test_select
|
|
1847
|
+
rfd1, wfd1 = UM.pipe
|
|
1848
|
+
rfd2, wfd2 = UM.pipe
|
|
1849
|
+
|
|
1850
|
+
events = []
|
|
1851
|
+
machine.spin do
|
|
1852
|
+
events << 1
|
|
1853
|
+
events << machine.select([rfd1, rfd2], [], [])
|
|
1854
|
+
events << 2
|
|
1855
|
+
events << machine.select([rfd1, rfd2], [], [])
|
|
1856
|
+
events << 3
|
|
1857
|
+
machine.snooze
|
|
1858
|
+
events << machine.select([], [wfd1, wfd2], [])
|
|
1859
|
+
events << 4
|
|
1860
|
+
end
|
|
1861
|
+
|
|
1862
|
+
machine.snooze
|
|
1863
|
+
assert_equal [1], events
|
|
1864
|
+
|
|
1865
|
+
machine.write(wfd1, 'foo')
|
|
1866
|
+
machine.snooze
|
|
1867
|
+
assert_equal [1, [[rfd1], [], []], 2], events
|
|
1868
|
+
|
|
1869
|
+
machine.write(wfd2, 'foo')
|
|
1870
|
+
|
|
1871
|
+
machine.snooze
|
|
1872
|
+
assert_equal [1, [[rfd1], [], []], 2, [[rfd1, rfd2], [], []], 3], events
|
|
1873
|
+
|
|
1874
|
+
machine.snooze
|
|
1875
|
+
|
|
1876
|
+
assert_equal [
|
|
1877
|
+
1, [[rfd1], [], []],
|
|
1878
|
+
2, [[rfd1, rfd2], [], []],
|
|
1879
|
+
3, [[], [wfd1, wfd2], []],
|
|
1880
|
+
4
|
|
1881
|
+
], events
|
|
1882
|
+
|
|
1883
|
+
machine.close(rfd1)
|
|
1884
|
+
machine.close(rfd2)
|
|
1885
|
+
end
|
|
1886
|
+
|
|
1887
|
+
def test_select_single
|
|
1888
|
+
rfd1, wfd1 = UM.pipe
|
|
1889
|
+
|
|
1890
|
+
events = []
|
|
1891
|
+
machine.spin do
|
|
1892
|
+
events << 1
|
|
1893
|
+
events << machine.select([rfd1], [], [])
|
|
1894
|
+
events << 2
|
|
1895
|
+
machine.snooze
|
|
1896
|
+
events << machine.select([], [wfd1], [])
|
|
1897
|
+
events << 3
|
|
1898
|
+
end
|
|
1899
|
+
|
|
1900
|
+
machine.snooze
|
|
1901
|
+
assert_equal [1], events
|
|
1902
|
+
|
|
1903
|
+
machine.write(wfd1, 'foo')
|
|
1904
|
+
machine.snooze
|
|
1905
|
+
assert_equal [1, [[rfd1], [], []], 2], events
|
|
1906
|
+
|
|
1907
|
+
3.times { machine.snooze }
|
|
1908
|
+
assert_equal [1, [[rfd1], [], []], 2, [[], [wfd1], []], 3], events
|
|
1909
|
+
|
|
1910
|
+
machine.close(rfd1)
|
|
1911
|
+
machine.close(wfd1)
|
|
1912
|
+
end
|
|
1913
|
+
|
|
1914
|
+
def test_select_empty
|
|
1915
|
+
ret = machine.select([], [], [])
|
|
1916
|
+
assert_equal [[], [], []], ret
|
|
1917
|
+
end
|
|
1918
|
+
|
|
1919
|
+
def test_select_bad_fd
|
|
1920
|
+
assert_raises(Errno::EBADF) { machine.select([9876, 9877], [], []) }
|
|
1921
|
+
end
|
|
1922
|
+
end
|
|
1372
1923
|
|
|
1924
|
+
class WaitidTest < UMBaseTest
|
|
1925
|
+
def test_waitid
|
|
1373
1926
|
msg = 'hello from child'
|
|
1927
|
+
_rfd, wfd = UM.pipe
|
|
1928
|
+
child_pid = fork do
|
|
1929
|
+
m = UM.new
|
|
1930
|
+
m.write(wfd, msg)
|
|
1931
|
+
m.close(wfd)
|
|
1932
|
+
exit 42
|
|
1933
|
+
end
|
|
1374
1934
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1935
|
+
pid, status = machine.waitid(UM::P_PID, child_pid, UM::WEXITED)
|
|
1936
|
+
assert_equal child_pid, pid
|
|
1937
|
+
assert_equal 42, status
|
|
1938
|
+
ensure
|
|
1939
|
+
Process.wait(child_pid) rescue nil
|
|
1940
|
+
end
|
|
1941
|
+
|
|
1942
|
+
def test_waitid_invalid_pid
|
|
1943
|
+
assert_raises(Errno::ECHILD) {
|
|
1944
|
+
machine.waitid(UM::P_PID, Process.pid + 1, UM::WEXITED)
|
|
1945
|
+
}
|
|
1946
|
+
end
|
|
1947
|
+
|
|
1948
|
+
def test_waitid_invalid_idtype
|
|
1949
|
+
assert_raises(Errno::EINVAL) {
|
|
1950
|
+
machine.waitid(1234, 0, UM::WEXITED)
|
|
1951
|
+
}
|
|
1952
|
+
end
|
|
1953
|
+
|
|
1954
|
+
def test_waitid_invalid_options
|
|
1955
|
+
assert_raises(Errno::EINVAL) {
|
|
1956
|
+
machine.waitid(P_ALL, 0, 1234)
|
|
1957
|
+
}
|
|
1958
|
+
end
|
|
1959
|
+
|
|
1960
|
+
def test_waitid_P_ALL
|
|
1961
|
+
msg = 'hello from child'
|
|
1962
|
+
_rfd, wfd = UM.pipe
|
|
1963
|
+
child_pid = fork do
|
|
1377
1964
|
m = UM.new
|
|
1378
1965
|
m.write(wfd, msg)
|
|
1379
1966
|
m.close(wfd)
|
|
1380
1967
|
exit 42
|
|
1381
1968
|
end
|
|
1382
1969
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
assert_equal
|
|
1970
|
+
pid, status = machine.waitid(UM::P_ALL, 0, UM::WEXITED)
|
|
1971
|
+
assert_equal child_pid, pid
|
|
1972
|
+
assert_equal 42, status
|
|
1973
|
+
ensure
|
|
1974
|
+
Process.wait(child_pid) rescue nil
|
|
1975
|
+
end
|
|
1386
1976
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1977
|
+
def test_waitid_P_PGID
|
|
1978
|
+
msg = 'hello from child'
|
|
1979
|
+
_rfd, wfd = UM.pipe
|
|
1980
|
+
child_pid = fork do
|
|
1981
|
+
m = UM.new
|
|
1982
|
+
m.write(wfd, msg)
|
|
1983
|
+
m.close(wfd)
|
|
1984
|
+
exit 42
|
|
1985
|
+
end
|
|
1986
|
+
|
|
1987
|
+
pid, status = machine.waitid(UM::P_PGID, Process.getpgrp, UM::WEXITED)
|
|
1988
|
+
assert_equal child_pid, pid
|
|
1989
|
+
assert_equal 42, status
|
|
1391
1990
|
ensure
|
|
1392
|
-
Process.wait(
|
|
1991
|
+
Process.wait(child_pid) rescue nil
|
|
1393
1992
|
end
|
|
1394
1993
|
|
|
1395
|
-
def
|
|
1396
|
-
skip if
|
|
1994
|
+
def test_waitid_status
|
|
1995
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
1397
1996
|
|
|
1398
1997
|
msg = 'hello from child'
|
|
1399
|
-
|
|
1400
|
-
rfd, wfd = UM.pipe
|
|
1998
|
+
_rfd, wfd = UM.pipe
|
|
1401
1999
|
pid = fork do
|
|
1402
2000
|
m = UM.new
|
|
1403
2001
|
m.write(wfd, msg)
|
|
@@ -1405,23 +2003,76 @@ class WaitTest < UMBaseTest
|
|
|
1405
2003
|
exit 42
|
|
1406
2004
|
end
|
|
1407
2005
|
|
|
1408
|
-
|
|
1409
|
-
assert_kind_of
|
|
1410
|
-
assert_equal
|
|
2006
|
+
status = machine.waitid_status(UM::P_PID, pid, UM::WEXITED)
|
|
2007
|
+
assert_kind_of Process::Status, status
|
|
2008
|
+
assert_equal pid, status.pid
|
|
2009
|
+
assert_equal 42, status.exitstatus
|
|
2010
|
+
ensure
|
|
2011
|
+
Process.wait(pid) rescue nil
|
|
2012
|
+
end
|
|
1411
2013
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
2014
|
+
def test_waitid_status_invalid_pid
|
|
2015
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
2016
|
+
|
|
2017
|
+
assert_raises(Errno::ECHILD) {
|
|
2018
|
+
machine.waitid_status(UM::P_PID, Process.pid + 1, UM::WEXITED)
|
|
2019
|
+
}
|
|
2020
|
+
end
|
|
2021
|
+
|
|
2022
|
+
def test_waitid_status_invalid_idtype
|
|
2023
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
2024
|
+
|
|
2025
|
+
assert_raises(Errno::EINVAL) {
|
|
2026
|
+
machine.waitid_status(1234, 0, UM::WEXITED)
|
|
2027
|
+
}
|
|
2028
|
+
end
|
|
2029
|
+
|
|
2030
|
+
def test_waitid_status_invalid_options
|
|
2031
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
1416
2032
|
|
|
2033
|
+
assert_raises(Errno::EINVAL) {
|
|
2034
|
+
machine.waitid_status(P_ALL, 0, 1234)
|
|
2035
|
+
}
|
|
2036
|
+
end
|
|
2037
|
+
|
|
2038
|
+
def test_waitid_status_P_ALL
|
|
2039
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
2040
|
+
|
|
2041
|
+
msg = 'hello from child'
|
|
2042
|
+
_rfd, wfd = UM.pipe
|
|
2043
|
+
pid = fork do
|
|
2044
|
+
m = UM.new
|
|
2045
|
+
m.write(wfd, msg)
|
|
2046
|
+
m.close(wfd)
|
|
2047
|
+
exit 42
|
|
2048
|
+
end
|
|
2049
|
+
|
|
2050
|
+
status = machine.waitid_status(UM::P_ALL, 0, UM::WEXITED)
|
|
2051
|
+
assert_kind_of Process::Status, status
|
|
2052
|
+
assert_equal pid, status.pid
|
|
2053
|
+
assert_equal 42, status.exitstatus
|
|
1417
2054
|
ensure
|
|
1418
|
-
Process.wait(pid) rescue
|
|
2055
|
+
Process.wait(pid) rescue nil
|
|
1419
2056
|
end
|
|
1420
2057
|
|
|
1421
|
-
def
|
|
1422
|
-
skip if
|
|
2058
|
+
def test_waitid_status_P_PGID
|
|
2059
|
+
skip if !machine.respond_to?(:waitid_status)
|
|
1423
2060
|
|
|
1424
|
-
|
|
2061
|
+
msg = 'hello from child'
|
|
2062
|
+
_rfd, wfd = UM.pipe
|
|
2063
|
+
pid = fork do
|
|
2064
|
+
m = UM.new
|
|
2065
|
+
m.write(wfd, msg)
|
|
2066
|
+
m.close(wfd)
|
|
2067
|
+
exit 42
|
|
2068
|
+
end
|
|
2069
|
+
|
|
2070
|
+
status = machine.waitid_status(UM::P_PGID, Process.getpgrp, UM::WEXITED)
|
|
2071
|
+
assert_kind_of Process::Status, status
|
|
2072
|
+
assert_equal pid, status.pid
|
|
2073
|
+
assert_equal 42, status.exitstatus
|
|
2074
|
+
ensure
|
|
2075
|
+
Process.wait(pid) rescue nil
|
|
1425
2076
|
end
|
|
1426
2077
|
end
|
|
1427
2078
|
|
|
@@ -1509,7 +2160,7 @@ class ForkTest < UMBaseTest
|
|
|
1509
2160
|
assert_equal 3, ret
|
|
1510
2161
|
assert_equal 'foo', buf
|
|
1511
2162
|
ensure
|
|
1512
|
-
Process.wait(child_pid) rescue
|
|
2163
|
+
Process.wait(child_pid) rescue nil
|
|
1513
2164
|
end
|
|
1514
2165
|
end
|
|
1515
2166
|
|
|
@@ -1573,3 +2224,20 @@ class SendBundleTest < UMBaseTest
|
|
|
1573
2224
|
assert_equal strs.map(&:to_s).join, buf
|
|
1574
2225
|
end
|
|
1575
2226
|
end
|
|
2227
|
+
|
|
2228
|
+
class NonBlockTest < UMBaseTest
|
|
2229
|
+
def test_io_nonblock?
|
|
2230
|
+
assert_equal false, UM.io_nonblock?(STDIN)
|
|
2231
|
+
end
|
|
2232
|
+
|
|
2233
|
+
def test_io_set_nonblock
|
|
2234
|
+
r, _w = IO.pipe
|
|
2235
|
+
assert_equal true, UM.io_nonblock?(r)
|
|
2236
|
+
|
|
2237
|
+
UM.io_set_nonblock(r, false)
|
|
2238
|
+
assert_equal false, UM.io_nonblock?(r)
|
|
2239
|
+
|
|
2240
|
+
UM.io_set_nonblock(r, true)
|
|
2241
|
+
assert_equal true, UM.io_nonblock?(r)
|
|
2242
|
+
end
|
|
2243
|
+
end
|