uringmachine 0.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +85 -0
  4. data/TODO.md +5 -0
  5. data/examples/echo_server.rb +18 -40
  6. data/examples/inout.rb +19 -0
  7. data/examples/nc.rb +36 -0
  8. data/ext/um/extconf.rb +6 -15
  9. data/ext/um/um.c +340 -53
  10. data/ext/um/um.h +33 -11
  11. data/ext/um/um_class.c +101 -119
  12. data/ext/um/um_const.c +184 -0
  13. data/ext/um/um_op.c +39 -18
  14. data/ext/um/um_utils.c +48 -3
  15. data/lib/uringmachine/version.rb +1 -1
  16. data/lib/uringmachine.rb +12 -0
  17. data/test/helper.rb +13 -12
  18. data/test/test_um.rb +301 -3
  19. data/vendor/liburing/.github/workflows/build.yml +29 -1
  20. data/vendor/liburing/.gitignore +1 -0
  21. data/vendor/liburing/CHANGELOG +15 -0
  22. data/vendor/liburing/CONTRIBUTING.md +165 -0
  23. data/vendor/liburing/configure +32 -0
  24. data/vendor/liburing/examples/Makefile +8 -1
  25. data/vendor/liburing/examples/kdigest.c +405 -0
  26. data/vendor/liburing/examples/proxy.c +75 -8
  27. data/vendor/liburing/liburing.pc.in +1 -1
  28. data/vendor/liburing/src/Makefile +16 -2
  29. data/vendor/liburing/src/include/liburing/io_uring.h +31 -0
  30. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  31. data/vendor/liburing/src/include/liburing.h +31 -4
  32. data/vendor/liburing/src/liburing-ffi.map +5 -0
  33. data/vendor/liburing/src/liburing.map +1 -0
  34. data/vendor/liburing/src/queue.c +3 -0
  35. data/vendor/liburing/src/register.c +36 -0
  36. data/vendor/liburing/src/sanitize.c +176 -0
  37. data/vendor/liburing/src/setup.c +1 -1
  38. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  39. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  40. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  41. data/vendor/liburing/test/917257daa0fe.c +7 -0
  42. data/vendor/liburing/test/Makefile +31 -4
  43. data/vendor/liburing/test/a0908ae19763.c +7 -0
  44. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  45. data/vendor/liburing/test/accept.c +14 -4
  46. data/vendor/liburing/test/b19062a56726.c +7 -0
  47. data/vendor/liburing/test/bind-listen.c +2 -2
  48. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  49. data/vendor/liburing/test/buf-ring.c +2 -0
  50. data/vendor/liburing/test/coredump.c +7 -0
  51. data/vendor/liburing/test/cq-overflow.c +13 -1
  52. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  53. data/vendor/liburing/test/defer-taskrun.c +2 -2
  54. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  55. data/vendor/liburing/test/defer.c +2 -2
  56. data/vendor/liburing/test/double-poll-crash.c +1 -1
  57. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  58. data/vendor/liburing/test/eventfd.c +0 -1
  59. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  60. data/vendor/liburing/test/fadvise.c +9 -26
  61. data/vendor/liburing/test/fdinfo.c +9 -1
  62. data/vendor/liburing/test/file-register.c +14 -2
  63. data/vendor/liburing/test/file-update.c +1 -1
  64. data/vendor/liburing/test/file-verify.c +27 -16
  65. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  66. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  67. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  68. data/vendor/liburing/test/fsnotify.c +1 -0
  69. data/vendor/liburing/test/futex.c +16 -4
  70. data/vendor/liburing/test/helpers.c +47 -0
  71. data/vendor/liburing/test/helpers.h +6 -0
  72. data/vendor/liburing/test/init-mem.c +5 -3
  73. data/vendor/liburing/test/io-cancel.c +0 -24
  74. data/vendor/liburing/test/io_uring_passthrough.c +2 -0
  75. data/vendor/liburing/test/io_uring_register.c +25 -6
  76. data/vendor/liburing/test/iopoll-leak.c +4 -0
  77. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  78. data/vendor/liburing/test/iopoll.c +3 -3
  79. data/vendor/liburing/test/kallsyms.c +203 -0
  80. data/vendor/liburing/test/link-timeout.c +159 -0
  81. data/vendor/liburing/test/linked-defer-close.c +224 -0
  82. data/vendor/liburing/test/madvise.c +12 -25
  83. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  84. data/vendor/liburing/test/min-timeout.c +0 -25
  85. data/vendor/liburing/test/mkdir.c +6 -0
  86. data/vendor/liburing/test/msg-ring.c +8 -2
  87. data/vendor/liburing/test/napi-test.c +15 -2
  88. data/vendor/liburing/test/no-mmap-inval.c +2 -0
  89. data/vendor/liburing/test/nop.c +44 -0
  90. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  91. data/vendor/liburing/test/open-close.c +40 -0
  92. data/vendor/liburing/test/openat2.c +37 -14
  93. data/vendor/liburing/test/poll-many.c +13 -7
  94. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  95. data/vendor/liburing/test/poll-v-poll.c +6 -3
  96. data/vendor/liburing/test/pollfree.c +148 -0
  97. data/vendor/liburing/test/read-mshot-empty.c +156 -153
  98. data/vendor/liburing/test/read-mshot.c +276 -27
  99. data/vendor/liburing/test/read-write.c +78 -13
  100. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  101. data/vendor/liburing/test/recv-msgall.c +5 -0
  102. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  103. data/vendor/liburing/test/recvsend_bundle.c +92 -29
  104. data/vendor/liburing/test/reg-fd-only.c +14 -4
  105. data/vendor/liburing/test/regbuf-clone.c +187 -0
  106. data/vendor/liburing/test/regbuf-merge.c +7 -0
  107. data/vendor/liburing/test/register-restrictions.c +86 -85
  108. data/vendor/liburing/test/rename.c +59 -1
  109. data/vendor/liburing/test/ringbuf-read.c +5 -0
  110. data/vendor/liburing/test/ringbuf-status.c +5 -1
  111. data/vendor/liburing/test/runtests.sh +16 -1
  112. data/vendor/liburing/test/send-zerocopy.c +59 -0
  113. data/vendor/liburing/test/short-read.c +1 -0
  114. data/vendor/liburing/test/socket.c +43 -0
  115. data/vendor/liburing/test/splice.c +3 -1
  116. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  117. data/vendor/liburing/test/sq-poll-share.c +2 -0
  118. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  119. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  120. data/vendor/liburing/test/sqpoll-sleep.c +1 -25
  121. data/vendor/liburing/test/statx.c +89 -0
  122. data/vendor/liburing/test/stdout.c +2 -0
  123. data/vendor/liburing/test/submit-and-wait.c +1 -25
  124. data/vendor/liburing/test/submit-reuse.c +4 -26
  125. data/vendor/liburing/test/symlink.c +12 -1
  126. data/vendor/liburing/test/sync-cancel.c +48 -21
  127. data/vendor/liburing/test/thread-exit.c +5 -0
  128. data/vendor/liburing/test/timeout-new.c +1 -26
  129. data/vendor/liburing/test/timeout.c +12 -26
  130. data/vendor/liburing/test/unlink.c +94 -1
  131. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  132. data/vendor/liburing/test/waitid.c +62 -8
  133. data/vendor/liburing/test/wq-aff.c +35 -0
  134. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  135. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  136. metadata +17 -4
  137. data/examples/event_loop.rb +0 -69
  138. data/examples/fibers.rb +0 -105
data/test/helper.rb CHANGED
@@ -3,8 +3,12 @@
3
3
  require 'bundler/setup'
4
4
  require_relative './coverage' if ENV['COVERAGE']
5
5
  require 'uringmachine'
6
+ require 'socket'
6
7
  require 'minitest/autorun'
7
8
 
9
+ STDOUT.sync = true
10
+ STDERR.sync = true
11
+
8
12
  module ::Kernel
9
13
  def debug(**h)
10
14
  k, v = h.first
@@ -46,18 +50,6 @@ module Minitest::Assertions
46
50
  end
47
51
  end
48
52
 
49
- class IOURingBaseTest < Minitest::Test
50
- attr_accessor :ring
51
-
52
- def setup
53
- @ring = IOU::Ring.new
54
- end
55
-
56
- def teardown
57
- ring.close
58
- end
59
- end
60
-
61
53
  class UMBaseTest < Minitest::Test
62
54
  attr_accessor :machine
63
55
 
@@ -66,5 +58,14 @@ class UMBaseTest < Minitest::Test
66
58
  end
67
59
 
68
60
  def teardown
61
+ # @machine&.cleanup
62
+ end
63
+
64
+ def assign_port
65
+ @@port_assign_mutex ||= Mutex.new
66
+ @@port_assign_mutex.synchronize do
67
+ @@port ||= 1024 + rand(60000)
68
+ @@port += 1
69
+ end
69
70
  end
70
71
  end
data/test/test_um.rb CHANGED
@@ -110,7 +110,7 @@ class SchedulingTest < UMBaseTest
110
110
  def test_timeout_with_raising_block
111
111
  e = nil
112
112
  begin
113
- machine.timeout(0.01, TOError) do
113
+ machine.timeout(0.1, TOError) do
114
114
  raise 'hi'
115
115
  end
116
116
  rescue => e
@@ -125,7 +125,7 @@ class SchedulingTest < UMBaseTest
125
125
  end
126
126
 
127
127
  def test_timeout_with_nothing_blocking
128
- v = machine.timeout(0.01, TOError) { 42 }
128
+ v = machine.timeout(0.1, TOError) { 42 }
129
129
 
130
130
  assert_equal 42, v
131
131
 
@@ -160,7 +160,9 @@ end
160
160
  class SleepTest < UMBaseTest
161
161
  def test_sleep
162
162
  t0 = monotonic_clock
163
+ assert_equal 0, machine.pending_count
163
164
  res = machine.sleep(0.1)
165
+ assert_equal 0, machine.pending_count
164
166
  t1 = monotonic_clock
165
167
  assert_in_range 0.09..0.13, t1 - t0
166
168
  assert_equal 0.1, res
@@ -173,7 +175,9 @@ class ReadTest < UMBaseTest
173
175
  w << 'foobar'
174
176
 
175
177
  buf = +''
178
+ assert_equal 0, machine.pending_count
176
179
  res = machine.read(r.fileno, buf, 3)
180
+ assert_equal 0, machine.pending_count
177
181
  assert_equal 3, res
178
182
  assert_equal 'foo', buf
179
183
 
@@ -189,7 +193,7 @@ class ReadTest < UMBaseTest
189
193
  assert_equal '', buf
190
194
  end
191
195
 
192
- def test_prep_read_bad_fd
196
+ def test_read_bad_fd
193
197
  _r, w = IO.pipe
194
198
 
195
199
  assert_raises(Errno::EBADF) do
@@ -334,3 +338,297 @@ class ReadEachTest < UMBaseTest
334
338
  assert_equal 0, machine.pending_count
335
339
  end
336
340
  end
341
+
342
+ class WriteTest < UMBaseTest
343
+ def test_write
344
+ r, w = IO.pipe
345
+
346
+ assert_equal 0, machine.pending_count
347
+ machine.write(w.fileno, 'foo')
348
+ assert_equal 0, machine.pending_count
349
+ assert_equal 'foo', r.readpartial(3)
350
+
351
+ machine.write(w.fileno, 'bar', 2)
352
+ assert_equal 'ba', r.readpartial(3)
353
+ end
354
+
355
+ def test_write_bad_fd
356
+ r, _w = IO.pipe
357
+
358
+ assert_equal 0, machine.pending_count
359
+ assert_raises(Errno::EBADF) do
360
+ machine.write(r.fileno, 'foo')
361
+ end
362
+ assert_equal 0, machine.pending_count
363
+ end
364
+ end
365
+
366
+ class Closetest < UMBaseTest
367
+ def test_close
368
+ r, w = IO.pipe
369
+ machine.write(w.fileno, 'foo')
370
+ assert_equal 'foo', r.readpartial(3)
371
+
372
+ assert_equal 0, machine.pending_count
373
+ machine.close(w.fileno)
374
+ assert_equal 0, machine.pending_count
375
+ assert_equal '', r.read
376
+
377
+ assert_raises(Errno::EBADF) { machine.close(w.fileno) }
378
+ end
379
+ end
380
+
381
+ class AcceptTest < UMBaseTest
382
+ def setup
383
+ super
384
+ @port = assign_port
385
+ @server = TCPServer.open('127.0.0.1', @port)
386
+ end
387
+
388
+ def teardown
389
+ @server&.close
390
+ super
391
+ end
392
+
393
+ def test_accept
394
+ conn = TCPSocket.new('127.0.0.1', @port)
395
+
396
+ assert_equal 0, machine.pending_count
397
+ fd = machine.accept(@server.fileno)
398
+ assert_equal 0, machine.pending_count
399
+ assert_kind_of Integer, fd
400
+ assert fd > 0
401
+
402
+ machine.write(fd, 'foo')
403
+ buf = conn.readpartial(3)
404
+
405
+ assert_equal 'foo', buf
406
+ end
407
+ end
408
+
409
+ class AcceptEachTest < UMBaseTest
410
+ def setup
411
+ super
412
+ @port = assign_port
413
+ @server = TCPServer.open('127.0.0.1', @port)
414
+ end
415
+
416
+ def teardown
417
+ @server&.close
418
+ super
419
+ end
420
+
421
+ def test_accept_each
422
+ conns = []
423
+ t = Thread.new do
424
+ sleep 0.1
425
+ 3.times { conns << TCPSocket.new('127.0.0.1', @port) }
426
+ end
427
+
428
+ count = 0
429
+ machine.accept_each(@server.fileno) do |fd|
430
+ count += 1
431
+ break if count == 3
432
+ end
433
+
434
+ assert_equal 3, count
435
+ assert_equal 1, machine.pending_count
436
+ machine.snooze
437
+ assert_equal 0, machine.pending_count
438
+ ensure
439
+ t&.kill
440
+ end
441
+ end
442
+
443
+ class SocketTest < UMBaseTest
444
+ def test_socket
445
+ assert_equal 0, machine.pending_count
446
+ fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0);
447
+ assert_equal 0, machine.pending_count
448
+ assert_kind_of Integer, fd
449
+ assert fd > 0
450
+
451
+ assert_raises(Errno::EDESTADDRREQ) { machine.write(fd, 'foo') }
452
+ end
453
+ end
454
+
455
+ class ConnectTest < UMBaseTest
456
+ def setup
457
+ super
458
+ @port = assign_port
459
+ @server = TCPServer.open('127.0.0.1', @port)
460
+ end
461
+
462
+ def teardown
463
+ @server&.close
464
+ super
465
+ end
466
+
467
+ def test_connect
468
+ t = Thread.new do
469
+ conn = @server.accept
470
+ conn.write('foobar')
471
+ sleep
472
+ end
473
+
474
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
475
+ assert_equal 0, machine.pending_count
476
+ res = machine.connect(fd, '127.0.0.1', @port)
477
+ assert_equal 0, machine.pending_count
478
+ assert_equal 0, res
479
+
480
+ buf = +''
481
+ res = machine.read(fd, buf, 42)
482
+ assert_equal 6, res
483
+ assert_equal 'foobar', buf
484
+ ensure
485
+ t&.kill
486
+ end
487
+
488
+ def test_connect_with_bad_addr
489
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
490
+ assert_equal 0, machine.pending_count
491
+ assert_raises(Errno::ENETUNREACH) { machine.connect(fd, 'a.b.c.d', @port) }
492
+ assert_equal 0, machine.pending_count
493
+ end
494
+ end
495
+
496
+ class SendTest < UMBaseTest
497
+ def setup
498
+ super
499
+ @port = assign_port
500
+ @server = TCPServer.open('127.0.0.1', @port)
501
+ end
502
+
503
+ def teardown
504
+ @server&.close
505
+ super
506
+ end
507
+
508
+ def test_send
509
+ t = Thread.new do
510
+ conn = @server.accept
511
+ str = conn.readpartial(42)
512
+ conn.write("You said: #{str}")
513
+ sleep
514
+ end
515
+
516
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
517
+ res = machine.connect(fd, '127.0.0.1', @port)
518
+ assert_equal 0, res
519
+
520
+ res = machine.send(fd, 'foobar', 6, 0)
521
+ assert_equal 6, res
522
+
523
+ buf = +''
524
+ res = machine.read(fd, buf, 42)
525
+ assert_equal 16, res
526
+ assert_equal 'You said: foobar', buf
527
+ ensure
528
+ t&.kill
529
+ end
530
+ end
531
+
532
+ class RecvTest < UMBaseTest
533
+ def setup
534
+ super
535
+ @port = assign_port
536
+ @server = TCPServer.open('127.0.0.1', @port)
537
+ end
538
+
539
+ def teardown
540
+ @server&.close
541
+ super
542
+ end
543
+
544
+ def test_recv
545
+ t = Thread.new do
546
+ conn = @server.accept
547
+ conn.write('foobar')
548
+ sleep
549
+ end
550
+
551
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
552
+ res = machine.connect(fd, '127.0.0.1', @port)
553
+ assert_equal 0, res
554
+
555
+ buf = +''
556
+ res = machine.recv(fd, buf, 42, 0)
557
+ assert_equal 6, res
558
+ assert_equal 'foobar', buf
559
+ ensure
560
+ t&.kill
561
+ end
562
+ end
563
+
564
+ class BindTest < UMBaseTest
565
+ def setup
566
+ super
567
+ @port = assign_port
568
+ end
569
+
570
+ def test_bind
571
+ assert_equal 0, machine.pending_count
572
+ fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0);
573
+ res = machine.bind(fd, '127.0.0.1', @port)
574
+ assert_equal 0, res
575
+ assert_equal 0, machine.pending_count
576
+
577
+ peer = UDPSocket.new
578
+ peer.connect('127.0.0.1', @port)
579
+ peer.send 'foo', 0
580
+
581
+ buf = +''
582
+ res = machine.recv(fd, buf, 8192, 0)
583
+ assert_equal 3, res
584
+ assert_equal 'foo', buf
585
+ end
586
+
587
+ def test_bind_invalid_args
588
+ assert_equal 0, machine.pending_count
589
+
590
+ fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0);
591
+ assert_raises(Errno::EACCES) { machine.bind(fd, 'foo.bar.baz', 3) }
592
+ assert_raises(Errno::EBADF) { machine.bind(-3, '127.0.01', 1234) }
593
+
594
+ assert_equal 0, machine.pending_count
595
+ end
596
+ end
597
+
598
+ class ListenTest < UMBaseTest
599
+ def setup
600
+ super
601
+ @port = assign_port
602
+ end
603
+
604
+ def test_listen
605
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
606
+ machine.bind(fd, '127.0.0.1', @port)
607
+ res = machine.listen(fd, 5)
608
+ assert_equal 0, res
609
+ assert_equal 0, machine.pending_count
610
+
611
+ conn = nil
612
+ t = Thread.new do
613
+ sleep 0.01
614
+ conn = TCPSocket.new('127.0.0.1', @port)
615
+ end
616
+
617
+ conn_fd = machine.accept(fd)
618
+ t.join
619
+ assert_kind_of TCPSocket, conn
620
+
621
+ machine.send(conn_fd, 'foo', 3, 0)
622
+
623
+ buf = conn.readpartial(42)
624
+ assert_equal 'foo', buf
625
+ ensure
626
+ t&.kill
627
+ end
628
+ end
629
+
630
+ class ConstTest < UMBaseTest
631
+ def test_constants
632
+ assert_equal UM::SOCK_STREAM, UM::SOCK_STREAM
633
+ end
634
+ end
@@ -7,7 +7,7 @@ on:
7
7
 
8
8
  jobs:
9
9
  build:
10
- runs-on: ubuntu-22.04
10
+ runs-on: ubuntu-24.04
11
11
 
12
12
  strategy:
13
13
  fail-fast: false
@@ -19,6 +19,15 @@ jobs:
19
19
  cxx_pkg: g++-x86-64-linux-gnu
20
20
  cc: x86_64-linux-gnu-gcc
21
21
  cxx: x86_64-linux-gnu-g++
22
+ sanitize: 0
23
+
24
+ # x86-64 gcc asan
25
+ - arch: x86_64
26
+ cc_pkg: gcc-x86-64-linux-gnu
27
+ cxx_pkg: g++-x86-64-linux-gnu
28
+ cc: x86_64-linux-gnu-gcc
29
+ cxx: x86_64-linux-gnu-g++
30
+ sanitize: 1
22
31
 
23
32
  # x86-64 clang
24
33
  - arch: x86_64
@@ -28,6 +37,7 @@ jobs:
28
37
  cxx: clang++
29
38
  liburing_extra_flags: -Wshorten-64-to-32
30
39
  extra_flags: -Wmissing-prototypes -Wstrict-prototypes -Wunreachable-code-loop-increment -Wunreachable-code -Wmissing-variable-declarations -Wextra-semi-stmt
40
+ sanitize: 0
31
41
 
32
42
  # x86 (32-bit) gcc
33
43
  - arch: i686
@@ -35,6 +45,7 @@ jobs:
35
45
  cxx_pkg: g++-i686-linux-gnu
36
46
  cc: i686-linux-gnu-gcc
37
47
  cxx: i686-linux-gnu-g++
48
+ sanitize: 0
38
49
 
39
50
  # aarch64 gcc
40
51
  - arch: aarch64
@@ -42,6 +53,7 @@ jobs:
42
53
  cxx_pkg: g++-aarch64-linux-gnu
43
54
  cc: aarch64-linux-gnu-gcc
44
55
  cxx: aarch64-linux-gnu-g++
56
+ sanitize: 0
45
57
 
46
58
  # arm (32-bit) gcc
47
59
  - arch: arm
@@ -49,6 +61,7 @@ jobs:
49
61
  cxx_pkg: g++-arm-linux-gnueabi
50
62
  cc: arm-linux-gnueabi-gcc
51
63
  cxx: arm-linux-gnueabi-g++
64
+ sanitize: 0
52
65
 
53
66
  # riscv64
54
67
  - arch: riscv64
@@ -56,6 +69,7 @@ jobs:
56
69
  cxx_pkg: g++-riscv64-linux-gnu
57
70
  cc: riscv64-linux-gnu-gcc
58
71
  cxx: riscv64-linux-gnu-g++
72
+ sanitize: 0
59
73
 
60
74
  # powerpc64
61
75
  - arch: powerpc64
@@ -63,6 +77,7 @@ jobs:
63
77
  cxx_pkg: g++-powerpc64-linux-gnu
64
78
  cc: powerpc64-linux-gnu-gcc
65
79
  cxx: powerpc64-linux-gnu-g++
80
+ sanitize: 0
66
81
 
67
82
  # powerpc
68
83
  - arch: powerpc
@@ -70,6 +85,7 @@ jobs:
70
85
  cxx_pkg: g++-powerpc-linux-gnu
71
86
  cc: powerpc-linux-gnu-gcc
72
87
  cxx: powerpc-linux-gnu-g++
88
+ sanitize: 0
73
89
 
74
90
  # alpha
75
91
  - arch: alpha
@@ -77,6 +93,7 @@ jobs:
77
93
  cxx_pkg: g++-alpha-linux-gnu
78
94
  cc: alpha-linux-gnu-gcc
79
95
  cxx: alpha-linux-gnu-g++
96
+ sanitize: 0
80
97
 
81
98
  # mips64
82
99
  - arch: mips64
@@ -84,6 +101,7 @@ jobs:
84
101
  cxx_pkg: g++-mips64-linux-gnuabi64
85
102
  cc: mips64-linux-gnuabi64-gcc
86
103
  cxx: mips64-linux-gnuabi64-g++
104
+ sanitize: 0
87
105
 
88
106
  # mips
89
107
  - arch: mips
@@ -91,6 +109,7 @@ jobs:
91
109
  cxx_pkg: g++-mips-linux-gnu
92
110
  cc: mips-linux-gnu-gcc
93
111
  cxx: mips-linux-gnu-g++
112
+ sanitize: 0
94
113
 
95
114
  # hppa
96
115
  - arch: hppa
@@ -98,9 +117,11 @@ jobs:
98
117
  cxx_pkg: g++-hppa-linux-gnu
99
118
  cc: hppa-linux-gnu-gcc
100
119
  cxx: hppa-linux-gnu-g++
120
+ sanitize: 0
101
121
 
102
122
  env:
103
123
  FLAGS: -g -O3 -Wall -Wextra -Werror -Wno-sign-compare ${{matrix.extra_flags}}
124
+ SANITIZE: ${{matrix.sanitize}}
104
125
 
105
126
  # Flags for building sources in src/ dir only.
106
127
  LIBURING_CFLAGS: ${{matrix.liburing_extra_flags}}
@@ -128,10 +149,17 @@ jobs:
128
149
  ${{matrix.cxx}} --version;
129
150
 
130
151
  - name: Build
152
+ if: ${{matrix.sanitizer == '0'}}
131
153
  run: |
132
154
  ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}};
133
155
  make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
134
156
 
157
+ - name: Build
158
+ if: ${{matrix.sanitizer == '1'}}
159
+ run: |
160
+ ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --enable-sanitizer;
161
+ make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
162
+
135
163
  - name: Test install command
136
164
  run: |
137
165
  sudo make install;
@@ -26,6 +26,7 @@
26
26
  /examples/proxy
27
27
  /examples/send-zerocopy
28
28
  /examples/rsrc-update-bench
29
+ /examples/kdigest
29
30
 
30
31
  /test/*.t
31
32
  /test/*.dmesg
@@ -1,3 +1,18 @@
1
+ liburing-2.8 release
2
+ - Add support for incrementally/partially consumed provided buffers,
3
+ usable with the provided buffer ring support.
4
+ - Add support for foo_and_wait_min_timeout(), where it's possible to
5
+ define a minimum timeout for waiting to get batches of completions,
6
+ but if that fails, extend for a longer timeout without having any
7
+ extra context switches.
8
+ - Add support for using different clock sources for completion waiting.
9
+ - Great increase coverage of test cases, test case improvements and
10
+ fixes.
11
+ - Man page updates
12
+ - Don't leak _GNU_SOURCE via pkb-config --cflags
13
+ - Support for address sanitizer
14
+ - Add examples/kdigest sample program
15
+
1
16
  liburing-2.7 release
2
17
 
3
18
  - Man page updates
@@ -0,0 +1,165 @@
1
+ Introduction
2
+ ============
3
+
4
+ liburing welcomes contributions, whether they be bug fixes, features, or
5
+ documentation additions/updates. However, we do have some rules in place
6
+ to govern the sanity of the project, and all contributions should follow
7
+ the guidelines in this document. The main reasons for the rules are:
8
+
9
+ 1) Keep the code consistent
10
+ 2) Keep the git repository consistent
11
+ 3) Maintain bisectability
12
+
13
+ Coding style
14
+ ============
15
+
16
+ Generally, all the code in liburing should follow the same style. A few
17
+ known exceptions exist, like syzbot test cases that got committed rather
18
+ than re-writing them in a saner format. Any change you make, please
19
+ follow the style of the code around you.
20
+
21
+ Commit format
22
+ =============
23
+
24
+ Each commit should do one thing, and one thing only. If you find yourself,
25
+ in the commit message, adding phrases like "Also do [...]" or "While in
26
+ here [...]", then that's a sign that the change should have been split
27
+ into multiple commits. If your change includes some refactoring of code to
28
+ make your change possible, then that refactoring should be a separate
29
+ commit, done first. That means this preparatory commit won't have any
30
+ functional changes, and hence should be a no-op. It also means that your
31
+ main commit, with the change that you actually care about, will be smaller
32
+ and easier to review.
33
+
34
+ Each commit must stand on its own in terms of what it provides, and how it
35
+ works. Lots of changes are just a single commit, but for something a bit
36
+ more involved, it's not uncommon to have a pull request contain multiple
37
+ commits. Make each commit as simple as possible, and not any simpler. We'd
38
+ much rather see 10 simple commits than 2 more complicated ones. If you
39
+ stumble across something that needs fixing while making an unrelated
40
+ change, then please make that change as a separate commit, explaining why
41
+ it's being made.
42
+
43
+ Each commit in a series must be buildable, it's not enough that the end
44
+ result is buildable. See reason 3 in the introduction for why that's the
45
+ case.
46
+
47
+ No fixup commits! Sometimes people post a change and errors are pointed
48
+ out in the commit, and the author then does a followup fix for that
49
+ error. This isn't acceptable, please squash fixup commits into the
50
+ commit that introduced the problem in the first place. This is done by
51
+ amending the fix into the original commit that caused the issue. You can
52
+ do that with git rebase -i <sha> and arrange the commit order such that
53
+ the fixup is right after the original commit, and then use 's' (for
54
+ squash) to squash the fixup into the original commit. Don't forget to
55
+ edit the commit message while doing that, as git will combine the two
56
+ commit messages into one. Or you can do it manually. Once done, force
57
+ push your rewritten git history. See reasons 1-3 in the introduction
58
+ series for why that is.
59
+
60
+ Commit message
61
+ ==============
62
+
63
+ A good commit explains the WHY of a commit - explain the reason for this
64
+ commit to exist. Don't explain what the code in commit does, that should
65
+ be readily apparent from just reading the code. If that isn't the case,
66
+ then a comment in the code is going to be more useful than a lengthy
67
+ explanation in the commit message. liburing commits use the following
68
+ format:
69
+
70
+ Title
71
+
72
+ Body of commit
73
+
74
+ Signed-off-by: ```My Identity <my@email.com>```
75
+
76
+ That is, a descriptive title on the first line, then an empty line, then
77
+ the body of the commit message, then an empty line, and finally an SOB
78
+ tag. The signed-off-by exists to provide proof of origin, see the
79
+ [DCO](https://developercertificate.org/).
80
+
81
+ Example commit:
82
+
83
+ ```
84
+ commit 0fe5c09195c0918f89582dd6ff098a58a0bdf62a
85
+ Author: Jens Axboe <axboe@kernel.dk>
86
+ Date: Fri Sep 6 15:54:04 2024 -0600
87
+
88
+ configure: fix ublk_cmd header check
89
+
90
+ The previous commit is mixing private structures and defines with public
91
+ uapi ones. Testing for UBLK_U_CMD_START_DEV is fine, CTRL_CMD_HAS_DATA
92
+ is not. And struct ublk_ctrl_cmd_data is not a public struct.
93
+
94
+ Fixes: 83bc535a3118 ("configure: don't enable ublk if modern commands not available")
95
+ Signed-off-by: Jens Axboe <axboe@kernel.dk>
96
+ ```
97
+
98
+ Since this change is pretty trivial, a huge explanation need not be given
99
+ as to the reasonings for the change. However, for more complicated
100
+ changes, better reasonings should be given.
101
+
102
+ A Fixes line can be added if this commit fixes an issue in a previous
103
+ commit. That kind of meta data can be useful down the line for finding
104
+ dependencies between commits. Adding the following to your .gitconfig:
105
+
106
+ ```
107
+ [pretty]
108
+ fixes = Fixes: %h (\"%s\")
109
+ ```
110
+
111
+ and running ```git fixes <sha>``` will then generate the correctly
112
+ formatted Fixes line for the commit. Likewise, other meta data can be:
113
+
114
+ Link: https://somesite/somewhere
115
+
116
+ can be useful to link to a discussion around the issue that led to this
117
+ commit, perhaps a bug report. This can be a GitHub issue as well. If a
118
+ commit closes/solves a GitHub issue, than:
119
+
120
+ Closes: https://github.com/axboe/liburing/issues/XXXX
121
+
122
+ can also be used.
123
+
124
+ Each commit message should be formatted so each full line is 72-74 chars
125
+ wide. For many of us, GitHub is not the primary location, and git log is
126
+ often used in a terminal to browse the repo. Breaking lines at 72-74
127
+ characters retains readability in an xterm/terminal.
128
+
129
+ Pull Requests
130
+ =============
131
+
132
+ The git repository itself is the canonical location for information. It's
133
+ quite fine to provide a lengthy explanation for a pull request on GitHub,
134
+ however please ensure that this doesn't come at the expense of the commit
135
+ messages themselves being lacking. The commit messages should stand on
136
+ their own and contain everything that you'd otherwise put in the PR
137
+ message. If you've worked on projects that send patches before, consider
138
+ the PR message similar to the cover letter for a series of patches.
139
+
140
+ Most contributors seem to use GH for sending patches, which is fine. If
141
+ you prefer using email, then patches can also be sent to the io_uring
142
+ mailing list: io-uring@vger.kernel.org.
143
+
144
+ liburing doesn't squash/rebase-on-merge, or other heinous practices
145
+ sometimes seen elsewhere. Whatever sha your commit has in your tree is
146
+ what it'll have in the upstream tree. Patches are applied directly, and
147
+ pull requests are merged with a merge commit. If meta data needs to go
148
+ into the merge commit, then it will go into the merge commit message.
149
+ This means that you don't need to continually rebase your changes on top
150
+ of the master branch.
151
+
152
+ Testing changes
153
+ ===============
154
+
155
+ You should ALWAYS test your changes, no matter how trivial or obviously
156
+ correct they may seem. Nobody is infallible, and making mistakes is only
157
+ human.
158
+
159
+ liburing contains a wide variety of functional tests. If you make changes
160
+ to liburing, then you should run the test cases. This is done by building
161
+ the repo and running ```make runtests```. Note that some of the liburing
162
+ tests test for defects in older kernels, and hence it's possible that they
163
+ will crash on an outdated kernel that doesn't contain fixes from the
164
+ stable kernel tree. If in doubt, building and running the tests in a vm is
165
+ encouraged.