polyphony 0.51.0 → 0.54.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -2
  3. data/CHANGELOG.md +26 -0
  4. data/Gemfile.lock +7 -68
  5. data/TODO.md +37 -6
  6. data/examples/core/forking.rb +2 -2
  7. data/examples/core/queue.rb +19 -0
  8. data/examples/io/echo_server.rb +1 -0
  9. data/examples/io/https_server.rb +30 -0
  10. data/examples/io/tcp_proxy.rb +2 -2
  11. data/ext/polyphony/backend_common.h +29 -6
  12. data/ext/polyphony/backend_io_uring.c +125 -23
  13. data/ext/polyphony/backend_io_uring_context.c +1 -0
  14. data/ext/polyphony/backend_io_uring_context.h +1 -0
  15. data/ext/polyphony/backend_libev.c +309 -21
  16. data/ext/polyphony/event.c +1 -1
  17. data/ext/polyphony/extconf.rb +9 -2
  18. data/ext/polyphony/polyphony.c +102 -0
  19. data/ext/polyphony/polyphony.h +32 -2
  20. data/ext/polyphony/polyphony_ext.c +3 -0
  21. data/ext/polyphony/queue.c +1 -1
  22. data/ext/polyphony/runqueue.c +1 -1
  23. data/ext/polyphony/socket_extensions.c +33 -0
  24. data/ext/polyphony/thread.c +8 -2
  25. data/lib/polyphony/adapters/irb.rb +1 -1
  26. data/lib/polyphony/adapters/mysql2.rb +1 -1
  27. data/lib/polyphony/adapters/postgres.rb +5 -5
  28. data/lib/polyphony/adapters/process.rb +2 -2
  29. data/lib/polyphony/core/global_api.rb +5 -5
  30. data/lib/polyphony/core/sync.rb +9 -1
  31. data/lib/polyphony/core/throttler.rb +1 -1
  32. data/lib/polyphony/core/timer.rb +2 -2
  33. data/lib/polyphony/extensions/core.rb +1 -1
  34. data/lib/polyphony/extensions/io.rb +20 -25
  35. data/lib/polyphony/extensions/openssl.rb +28 -21
  36. data/lib/polyphony/extensions/socket.rb +51 -54
  37. data/lib/polyphony/version.rb +1 -1
  38. data/polyphony.gemspec +6 -5
  39. data/test/helper.rb +1 -1
  40. data/test/stress.rb +2 -0
  41. data/test/test_backend.rb +152 -5
  42. data/test/test_global_api.rb +2 -2
  43. data/test/test_io.rb +33 -2
  44. data/test/test_kernel.rb +1 -1
  45. data/test/test_signal.rb +1 -1
  46. data/test/test_socket.rb +27 -0
  47. data/test/test_sync.rb +43 -0
  48. data/test/test_thread.rb +4 -0
  49. data/test/test_timer.rb +1 -1
  50. metadata +10 -49
@@ -10,6 +10,7 @@ const char *op_type_to_str(enum op_type type) {
10
10
  case OP_WRITE: return "WRITE";
11
11
  case OP_RECV: return "RECV";
12
12
  case OP_SEND: return "SEND";
13
+ case OP_SPLICE: return "SPLICE";
13
14
  case OP_TIMEOUT: return "TIMEOUT";
14
15
  case OP_POLL: return "POLL";
15
16
  case OP_ACCEPT: return "ACCEPT";
@@ -10,6 +10,7 @@ enum op_type {
10
10
  OP_WRITE,
11
11
  OP_RECV,
12
12
  OP_SEND,
13
+ OP_SPLICE,
13
14
  OP_TIMEOUT,
14
15
  OP_POLL,
15
16
  OP_ACCEPT,
@@ -1,10 +1,52 @@
1
+ /*
2
+ # Libev-based blocking ops backend for Polyphony
3
+
4
+ ## Backend initialization
5
+
6
+ The backend is initialized by creating an event loop. For the main thread the
7
+ default event loop is used, but we since we don't need to handle any signals
8
+ (see the waitpid implementation below) we might as well use a non-default event
9
+ loop for the main thread at some time in the future.
10
+
11
+ In addition, we create an async watcher that is used for interrupting the #poll
12
+ method from another thread.
13
+
14
+ ## Blocking operations
15
+
16
+ I/O operations start by making sure the io has been set to non-blocking
17
+ operation (O_NONBLOCK). That way, if the syscall would block, we'd get an
18
+ EWOULDBLOCK or EAGAIN instead of blocking.
19
+
20
+ Once the OS has indicated that the operation would block, we start a watcher
21
+ (its type corresponding to the desired operation), and call ev_xxxx_start. in We
22
+ then call Thread_switch_fiber and switch to another fiber while waiting for the
23
+ watcher to be triggered.
24
+
25
+ ## Polling for events
26
+
27
+ Backend_poll is called either once the corresponding thread has no more work to
28
+ do (no runnable fibers) or periodically while the thread is scheduling fibers in
29
+ order to prevent event starvation.
30
+
31
+ ## Behaviour of waitpid
32
+
33
+ On Linux 5.3+, pidfd_open will be used, otherwise a libev child watcher will be
34
+ used. Note that if a child watcher is used, waitpid will only work from the main
35
+ thread.
36
+
37
+ */
38
+
1
39
  #ifdef POLYPHONY_BACKEND_LIBEV
2
40
 
41
+ #ifdef POLYPHONY_LINUX
42
+ #define _GNU_SOURCE 1
43
+ #endif
44
+
45
+ #include <fcntl.h>
3
46
  #include <netdb.h>
4
47
  #include <sys/socket.h>
5
48
  #include <sys/uio.h>
6
49
  #include <unistd.h>
7
- #include <fcntl.h>
8
50
  #include <netinet/in.h>
9
51
  #include <arpa/inet.h>
10
52
  #include <stdnoreturn.h>
@@ -16,6 +58,9 @@
16
58
  #include "ruby/io.h"
17
59
 
18
60
  VALUE SYM_libev;
61
+ VALUE SYM_send;
62
+ VALUE SYM_splice;
63
+ VALUE SYM_write;
19
64
 
20
65
  ID ID_ivar_is_nonblocking;
21
66
 
@@ -76,17 +121,27 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
76
121
  // of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
77
122
  }
78
123
 
124
+ inline struct ev_loop *libev_new_loop() {
125
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
126
+ return ev_loop_new(EVFLAG_NOSIGMASK);
127
+ #else
128
+ int is_main_thread = (rb_thread_current() == rb_thread_main());
129
+ return is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
130
+ #endif
131
+ }
132
+
79
133
  static VALUE Backend_initialize(VALUE self) {
80
134
  Backend_t *backend;
81
- VALUE thread = rb_thread_current();
82
- int is_main_thread = (thread == rb_thread_main());
83
-
135
+
84
136
  GetBackend(self, backend);
85
- backend->ev_loop = is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
137
+ backend->ev_loop = libev_new_loop();
86
138
 
139
+ // start async watcher used for breaking a poll op (from another thread)
87
140
  ev_async_init(&backend->break_async, break_async_callback);
88
141
  ev_async_start(backend->ev_loop, &backend->break_async);
89
- ev_unref(backend->ev_loop); // don't count the break_async watcher
142
+ // the break_async watcher is unreferenced, in order for Backend_poll to not
143
+ // block when no other watcher is active
144
+ ev_unref(backend->ev_loop);
90
145
 
91
146
  backend->currently_polling = 0;
92
147
  backend->pending_count = 0;
@@ -672,6 +727,167 @@ error:
672
727
  return RAISE_EXCEPTION(switchpoint_result);
673
728
  }
674
729
 
730
+ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
731
+ Backend_t *backend;
732
+ struct libev_io watcher;
733
+ rb_io_t *fptr;
734
+ VALUE switchpoint_result = Qnil;
735
+ VALUE underlying_io;
736
+ char *buf = StringValuePtr(str);
737
+ long len = RSTRING_LEN(str);
738
+ long left = len;
739
+ int flags_int = NUM2INT(flags);
740
+
741
+ underlying_io = rb_ivar_get(io, ID_ivar_io);
742
+ if (underlying_io != Qnil) io = underlying_io;
743
+ GetBackend(self, backend);
744
+ io = rb_io_get_write_io(io);
745
+ GetOpenFile(io, fptr);
746
+ io_set_nonblock(fptr, io);
747
+ watcher.fiber = Qnil;
748
+
749
+ while (left > 0) {
750
+ ssize_t n = send(fptr->fd, buf, left, flags_int);
751
+ if (n < 0) {
752
+ int e = errno;
753
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
754
+
755
+ switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
756
+
757
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
758
+ }
759
+ else {
760
+ buf += n;
761
+ left -= n;
762
+ }
763
+ }
764
+
765
+ if (watcher.fiber == Qnil) {
766
+ switchpoint_result = backend_snooze();
767
+
768
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
769
+ }
770
+
771
+ RB_GC_GUARD(watcher.fiber);
772
+ RB_GC_GUARD(switchpoint_result);
773
+
774
+ return INT2NUM(len);
775
+ error:
776
+ return RAISE_EXCEPTION(switchpoint_result);
777
+ }
778
+
779
+ #ifdef POLYPHONY_LINUX
780
+ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
781
+ Backend_t *backend;
782
+ struct libev_io watcher;
783
+ VALUE switchpoint_result = Qnil;
784
+ VALUE underlying_io;
785
+ rb_io_t *src_fptr;
786
+ rb_io_t *dest_fptr;
787
+ int len;
788
+
789
+ GetBackend(self, backend);
790
+
791
+ underlying_io = rb_ivar_get(src, ID_ivar_io);
792
+ if (underlying_io != Qnil) src = underlying_io;
793
+ GetOpenFile(src, src_fptr);
794
+ io_set_nonblock(src_fptr, src);
795
+
796
+ underlying_io = rb_ivar_get(dest, ID_ivar_io);
797
+ if (underlying_io != Qnil) dest = underlying_io;
798
+ dest = rb_io_get_write_io(dest);
799
+ GetOpenFile(dest, dest_fptr);
800
+ io_set_nonblock(dest_fptr, dest);
801
+
802
+ watcher.fiber = Qnil;
803
+ while (1) {
804
+ len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
805
+ if (len < 0) {
806
+ int e = errno;
807
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
808
+
809
+ switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
810
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
811
+
812
+ switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
813
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
814
+ }
815
+ else {
816
+ break;
817
+ }
818
+ }
819
+
820
+ if (watcher.fiber == Qnil) {
821
+ switchpoint_result = backend_snooze();
822
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
823
+ }
824
+
825
+ RB_GC_GUARD(watcher.fiber);
826
+ RB_GC_GUARD(switchpoint_result);
827
+
828
+ return INT2NUM(len);
829
+ error:
830
+ return RAISE_EXCEPTION(switchpoint_result);
831
+ }
832
+
833
+ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
834
+ Backend_t *backend;
835
+ struct libev_io watcher;
836
+ VALUE switchpoint_result = Qnil;
837
+ VALUE underlying_io;
838
+ rb_io_t *src_fptr;
839
+ rb_io_t *dest_fptr;
840
+ int len;
841
+ int total = 0;
842
+
843
+ GetBackend(self, backend);
844
+
845
+ underlying_io = rb_ivar_get(src, ID_ivar_io);
846
+ if (underlying_io != Qnil) src = underlying_io;
847
+ GetOpenFile(src, src_fptr);
848
+ io_set_nonblock(src_fptr, src);
849
+
850
+ underlying_io = rb_ivar_get(dest, ID_ivar_io);
851
+ if (underlying_io != Qnil) dest = underlying_io;
852
+ dest = rb_io_get_write_io(dest);
853
+ GetOpenFile(dest, dest_fptr);
854
+ io_set_nonblock(dest_fptr, dest);
855
+
856
+ watcher.fiber = Qnil;
857
+ while (1) {
858
+ len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
859
+ if (len < 0) {
860
+ int e = errno;
861
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
862
+
863
+ switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
864
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
865
+
866
+ switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
867
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
868
+ }
869
+ else if (len == 0) {
870
+ break;
871
+ }
872
+ else {
873
+ total += len;
874
+ }
875
+ }
876
+
877
+ if (watcher.fiber == Qnil) {
878
+ switchpoint_result = backend_snooze();
879
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
880
+ }
881
+
882
+ RB_GC_GUARD(watcher.fiber);
883
+ RB_GC_GUARD(switchpoint_result);
884
+
885
+ return INT2NUM(total);
886
+ error:
887
+ return RAISE_EXCEPTION(switchpoint_result);
888
+ }
889
+ #endif
890
+
675
891
  VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
676
892
  Backend_t *backend;
677
893
  rb_io_t *fptr;
@@ -799,6 +1015,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
799
1015
  return result;
800
1016
  }
801
1017
 
1018
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
802
1019
  VALUE Backend_waitpid(VALUE self, VALUE pid) {
803
1020
  int pid_int = NUM2INT(pid);
804
1021
  int fd = pidfd_open(pid_int, 0);
@@ -811,18 +1028,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
811
1028
  RAISE_IF_EXCEPTION(resume_value);
812
1029
  RB_GC_GUARD(resume_value);
813
1030
  }
1031
+ else {
1032
+ int e = errno;
1033
+ rb_syserr_fail(e, strerror(e));
1034
+ }
814
1035
 
815
1036
  int status = 0;
816
1037
  pid_t ret = waitpid(pid_int, &status, WNOHANG);
817
1038
  if (ret < 0) {
818
1039
  int e = errno;
819
- if (e == ECHILD)
820
- ret = pid_int;
821
- else
822
- rb_syserr_fail(e, strerror(e));
1040
+ rb_syserr_fail(e, strerror(e));
823
1041
  }
824
1042
  return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
825
1043
  }
1044
+ #else
1045
+ struct libev_child {
1046
+ struct ev_child child;
1047
+ VALUE fiber;
1048
+ };
1049
+
1050
+ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
1051
+ struct libev_child *watcher = (struct libev_child *)w;
1052
+ int exit_status = WEXITSTATUS(w->rstatus);
1053
+ VALUE status;
1054
+
1055
+ status = rb_ary_new_from_args(2, INT2NUM(w->rpid), INT2NUM(exit_status));
1056
+ Fiber_make_runnable(watcher->fiber, status);
1057
+ }
1058
+
1059
+ VALUE Backend_waitpid(VALUE self, VALUE pid) {
1060
+ Backend_t *backend;
1061
+ struct libev_child watcher;
1062
+ VALUE switchpoint_result = Qnil;
1063
+ GetBackend(self, backend);
1064
+
1065
+ watcher.fiber = rb_fiber_current();
1066
+ ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
1067
+ ev_child_start(backend->ev_loop, &watcher.child);
1068
+
1069
+ switchpoint_result = backend_await(backend);
1070
+
1071
+ ev_child_stop(backend->ev_loop, &watcher.child);
1072
+ RAISE_IF_EXCEPTION(switchpoint_result);
1073
+ RB_GC_GUARD(watcher.fiber);
1074
+ RB_GC_GUARD(switchpoint_result);
1075
+ return switchpoint_result;
1076
+ }
1077
+ #endif
826
1078
 
827
1079
  void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
828
1080
 
@@ -848,10 +1100,35 @@ VALUE Backend_kind(VALUE self) {
848
1100
  return SYM_libev;
849
1101
  }
850
1102
 
1103
+ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
1104
+ VALUE result = Qnil;
1105
+ if (argc == 0) return result;
1106
+
1107
+ for (int i = 0; i < argc; i++) {
1108
+ VALUE op = argv[i];
1109
+ VALUE op_type = RARRAY_AREF(op, 0);
1110
+ VALUE op_len = RARRAY_LEN(op);
1111
+
1112
+ if (op_type == SYM_write && op_len == 3)
1113
+ result = Backend_write(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
1114
+ else if (op_type == SYM_send && op_len == 4)
1115
+ result = Backend_send(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
1116
+ #ifdef POLYPHONY_LINUX
1117
+ else if (op_type == SYM_splice && op_len == 4)
1118
+ result = Backend_splice(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
1119
+ #endif
1120
+ else
1121
+ rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
1122
+ }
1123
+
1124
+ RB_GC_GUARD(result);
1125
+ return result;
1126
+ }
1127
+
851
1128
  void Init_Backend() {
852
1129
  ev_set_allocator(xrealloc);
853
1130
 
854
- VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
1131
+ VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
855
1132
  rb_define_alloc_func(cBackend, Backend_allocate);
856
1133
 
857
1134
  rb_define_method(cBackend, "initialize", Backend_initialize, 0);
@@ -860,29 +1137,40 @@ void Init_Backend() {
860
1137
 
861
1138
  rb_define_method(cBackend, "poll", Backend_poll, 3);
862
1139
  rb_define_method(cBackend, "break", Backend_wakeup, 0);
1140
+ rb_define_method(cBackend, "kind", Backend_kind, 0);
1141
+ rb_define_method(cBackend, "chain", Backend_chain, -1);
863
1142
 
864
- rb_define_method(cBackend, "read", Backend_read, 4);
865
- rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
866
- rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
867
- rb_define_method(cBackend, "write", Backend_write_m, -1);
868
1143
  rb_define_method(cBackend, "accept", Backend_accept, 2);
869
1144
  rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
870
1145
  rb_define_method(cBackend, "connect", Backend_connect, 3);
1146
+ rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
1147
+ rb_define_method(cBackend, "read", Backend_read, 4);
1148
+ rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
871
1149
  rb_define_method(cBackend, "recv", Backend_recv, 3);
872
1150
  rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
873
1151
  rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
874
- rb_define_method(cBackend, "send", Backend_write, 2);
875
- rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
1152
+ rb_define_method(cBackend, "send", Backend_send, 3);
1153
+ rb_define_method(cBackend, "sendv", Backend_sendv, 3);
876
1154
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
877
- rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
1155
+
1156
+ #ifdef POLYPHONY_LINUX
1157
+ rb_define_method(cBackend, "splice", Backend_splice, 3);
1158
+ rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
1159
+ #endif
1160
+
878
1161
  rb_define_method(cBackend, "timeout", Backend_timeout, -1);
879
- rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
1162
+ rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
880
1163
  rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
881
-
882
- rb_define_method(cBackend, "kind", Backend_kind, 0);
1164
+ rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
1165
+ rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
1166
+ rb_define_method(cBackend, "write", Backend_write_m, -1);
883
1167
 
884
1168
  ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
885
1169
  SYM_libev = ID2SYM(rb_intern("libev"));
1170
+
1171
+ SYM_send = ID2SYM(rb_intern("send"));
1172
+ SYM_splice = ID2SYM(rb_intern("splice"));
1173
+ SYM_write = ID2SYM(rb_intern("write"));
886
1174
  }
887
1175
 
888
1176
  #endif // POLYPHONY_BACKEND_LIBEV
@@ -77,7 +77,7 @@ VALUE Event_await(VALUE self) {
77
77
  }
78
78
 
79
79
  void Init_Event() {
80
- cEvent = rb_define_class_under(mPolyphony, "Event", rb_cData);
80
+ cEvent = rb_define_class_under(mPolyphony, "Event", rb_cObject);
81
81
  rb_define_alloc_func(cEvent, Event_allocate);
82
82
 
83
83
  rb_define_method(cEvent, "initialize", Event_initialize, 0);
@@ -4,18 +4,24 @@ require 'rubygems'
4
4
  require 'mkmf'
5
5
 
6
6
  use_liburing = false
7
+ use_pidfd_open = false
7
8
  force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
9
+ linux = RUBY_PLATFORM =~ /linux/
8
10
 
9
- if !force_use_libev && RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
11
+ if linux && `uname -sr` =~ /Linux 5\.([\d+])/
10
12
  kernel_minor_version = $1.gsub('.', '').to_i
11
- use_liburing = kernel_minor_version >= 6
13
+ use_liburing = !force_use_libev && kernel_minor_version >= 6
14
+ use_pidfd_open = kernel_minor_version >= 3
12
15
  end
13
16
 
17
+ $defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
14
18
  if use_liburing
15
19
  $defs << "-DPOLYPHONY_BACKEND_LIBURING"
20
+ $defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
16
21
  $CFLAGS << " -Wno-pointer-arith"
17
22
  else
18
23
  $defs << "-DPOLYPHONY_BACKEND_LIBEV"
24
+ $defs << "-DPOLYPHONY_LINUX" if linux
19
25
  $defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
20
26
  $defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
21
27
  $defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
@@ -23,6 +29,7 @@ else
23
29
  $defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
24
30
  $defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
25
31
  $defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
32
+
26
33
  $CFLAGS << " -Wno-comment"
27
34
  $CFLAGS << " -Wno-unused-result"
28
35
  $CFLAGS << " -Wno-dangling-else"