polyphony 0.51.0 → 0.52.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,41 @@
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
 
3
41
  #include <netdb.h>
@@ -76,17 +114,27 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
76
114
  // of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
77
115
  }
78
116
 
117
+ inline struct ev_loop *libev_new_loop() {
118
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
119
+ return ev_loop_new(EVFLAG_NOSIGMASK);
120
+ #else
121
+ int is_main_thread = (rb_thread_current() == rb_thread_main());
122
+ return is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
123
+ #endif
124
+ }
125
+
79
126
  static VALUE Backend_initialize(VALUE self) {
80
127
  Backend_t *backend;
81
- VALUE thread = rb_thread_current();
82
- int is_main_thread = (thread == rb_thread_main());
83
-
128
+
84
129
  GetBackend(self, backend);
85
- backend->ev_loop = is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
130
+ backend->ev_loop = libev_new_loop();
86
131
 
132
+ // start async watcher used for breaking a poll op (from another thread)
87
133
  ev_async_init(&backend->break_async, break_async_callback);
88
134
  ev_async_start(backend->ev_loop, &backend->break_async);
89
- ev_unref(backend->ev_loop); // don't count the break_async watcher
135
+ // the break_async watcher is unreferenced, in order for Backend_poll to not
136
+ // block when no other watcher is active
137
+ ev_unref(backend->ev_loop);
90
138
 
91
139
  backend->currently_polling = 0;
92
140
  backend->pending_count = 0;
@@ -672,6 +720,55 @@ error:
672
720
  return RAISE_EXCEPTION(switchpoint_result);
673
721
  }
674
722
 
723
+ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
724
+ Backend_t *backend;
725
+ struct libev_io watcher;
726
+ rb_io_t *fptr;
727
+ VALUE switchpoint_result = Qnil;
728
+ VALUE underlying_io;
729
+ char *buf = StringValuePtr(str);
730
+ long len = RSTRING_LEN(str);
731
+ long left = len;
732
+ int flags_int = NUM2INT(flags);
733
+
734
+ underlying_io = rb_ivar_get(io, ID_ivar_io);
735
+ if (underlying_io != Qnil) io = underlying_io;
736
+ GetBackend(self, backend);
737
+ io = rb_io_get_write_io(io);
738
+ GetOpenFile(io, fptr);
739
+ io_set_nonblock(fptr, io);
740
+ watcher.fiber = Qnil;
741
+
742
+ while (left > 0) {
743
+ ssize_t n = send(fptr->fd, buf, left, flags_int);
744
+ if (n < 0) {
745
+ int e = errno;
746
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
747
+
748
+ switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
749
+
750
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
751
+ }
752
+ else {
753
+ buf += n;
754
+ left -= n;
755
+ }
756
+ }
757
+
758
+ if (watcher.fiber == Qnil) {
759
+ switchpoint_result = backend_snooze();
760
+
761
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
762
+ }
763
+
764
+ RB_GC_GUARD(watcher.fiber);
765
+ RB_GC_GUARD(switchpoint_result);
766
+
767
+ return INT2NUM(len);
768
+ error:
769
+ return RAISE_EXCEPTION(switchpoint_result);
770
+ }
771
+
675
772
  VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
676
773
  Backend_t *backend;
677
774
  rb_io_t *fptr;
@@ -799,6 +896,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
799
896
  return result;
800
897
  }
801
898
 
899
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
802
900
  VALUE Backend_waitpid(VALUE self, VALUE pid) {
803
901
  int pid_int = NUM2INT(pid);
804
902
  int fd = pidfd_open(pid_int, 0);
@@ -811,18 +909,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
811
909
  RAISE_IF_EXCEPTION(resume_value);
812
910
  RB_GC_GUARD(resume_value);
813
911
  }
912
+ else {
913
+ int e = errno;
914
+ rb_syserr_fail(e, strerror(e));
915
+ }
814
916
 
815
917
  int status = 0;
816
918
  pid_t ret = waitpid(pid_int, &status, WNOHANG);
817
919
  if (ret < 0) {
818
920
  int e = errno;
819
- if (e == ECHILD)
820
- ret = pid_int;
821
- else
822
- rb_syserr_fail(e, strerror(e));
921
+ rb_syserr_fail(e, strerror(e));
823
922
  }
824
923
  return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
825
924
  }
925
+ #else
926
+ struct libev_child {
927
+ struct ev_child child;
928
+ VALUE fiber;
929
+ };
930
+
931
+ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
932
+ struct libev_child *watcher = (struct libev_child *)w;
933
+ int exit_status = WEXITSTATUS(w->rstatus);
934
+ VALUE status;
935
+
936
+ status = rb_ary_new_from_args(2, INT2NUM(w->rpid), INT2NUM(exit_status));
937
+ Fiber_make_runnable(watcher->fiber, status);
938
+ }
939
+
940
+ VALUE Backend_waitpid(VALUE self, VALUE pid) {
941
+ Backend_t *backend;
942
+ struct libev_child watcher;
943
+ VALUE switchpoint_result = Qnil;
944
+ GetBackend(self, backend);
945
+
946
+ watcher.fiber = rb_fiber_current();
947
+ ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
948
+ ev_child_start(backend->ev_loop, &watcher.child);
949
+
950
+ switchpoint_result = backend_await(backend);
951
+
952
+ ev_child_stop(backend->ev_loop, &watcher.child);
953
+ RAISE_IF_EXCEPTION(switchpoint_result);
954
+ RB_GC_GUARD(watcher.fiber);
955
+ RB_GC_GUARD(switchpoint_result);
956
+ return switchpoint_result;
957
+ }
958
+ #endif
826
959
 
827
960
  void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
828
961
 
@@ -851,7 +984,7 @@ VALUE Backend_kind(VALUE self) {
851
984
  void Init_Backend() {
852
985
  ev_set_allocator(xrealloc);
853
986
 
854
- VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
987
+ VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
855
988
  rb_define_alloc_func(cBackend, Backend_allocate);
856
989
 
857
990
  rb_define_method(cBackend, "initialize", Backend_initialize, 0);
@@ -871,7 +1004,8 @@ void Init_Backend() {
871
1004
  rb_define_method(cBackend, "recv", Backend_recv, 3);
872
1005
  rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
873
1006
  rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
874
- rb_define_method(cBackend, "send", Backend_write, 2);
1007
+ rb_define_method(cBackend, "send", Backend_send, 3);
1008
+ rb_define_method(cBackend, "sendv", Backend_sendv, 3);
875
1009
  rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
876
1010
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
877
1011
  rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
@@ -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,15 +4,19 @@ 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
8
9
 
9
- if !force_use_libev && RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
10
+ if RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
10
11
  kernel_minor_version = $1.gsub('.', '').to_i
11
- use_liburing = kernel_minor_version >= 6
12
+ use_liburing = !force_use_libev && kernel_minor_version >= 6
13
+ use_pidfd_open = kernel_minor_version >= 3
12
14
  end
13
15
 
16
+ $defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
14
17
  if use_liburing
15
18
  $defs << "-DPOLYPHONY_BACKEND_LIBURING"
19
+ $defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
16
20
  $CFLAGS << " -Wno-pointer-arith"
17
21
  else
18
22
  $defs << "-DPOLYPHONY_BACKEND_LIBEV"
@@ -23,6 +27,7 @@ else
23
27
  $defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
24
28
  $defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
25
29
  $defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
30
+
26
31
  $CFLAGS << " -Wno-comment"
27
32
  $CFLAGS << " -Wno-unused-result"
28
33
  $CFLAGS << " -Wno-dangling-else"
@@ -46,11 +46,105 @@ VALUE Polyphony_trace(VALUE self, VALUE enabled) {
46
46
  return Qnil;
47
47
  }
48
48
 
49
+ #define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
50
+
51
+ VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
52
+ return Backend_accept(BACKEND(), server_socket, socket_class);
53
+ }
54
+
55
+ VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
56
+ return Backend_accept_loop(BACKEND(), server_socket, socket_class);
57
+ }
58
+
59
+ VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
60
+ return Backend_connect(BACKEND(), io, addr, port);
61
+ }
62
+
63
+ VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
64
+ return Backend_feed_loop(BACKEND(), io, receiver, method);
65
+ }
66
+
67
+ VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
68
+ return Backend_read(BACKEND(), io, str, length, to_eof);
69
+ }
70
+
71
+ VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
72
+ return Backend_read_loop(BACKEND(), io);
73
+ }
74
+
75
+ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
76
+ return Backend_recv(BACKEND(), io, str, length);
77
+ }
78
+
79
+ VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
80
+ return Backend_recv_loop(BACKEND(), io);
81
+ }
82
+
83
+ VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
84
+ return Backend_recv_feed_loop(BACKEND(), io, receiver, method);
85
+ }
86
+
87
+ VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
88
+ return Backend_send(BACKEND(), io, msg, flags);
89
+ }
90
+
91
+ VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
92
+ return Backend_sendv(BACKEND(), io, ary, flags);
93
+ }
94
+
95
+ VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
96
+ return Backend_sleep(BACKEND(), duration);
97
+ }
98
+
99
+ VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
100
+ return Backend_timeout(argc, argv, BACKEND());
101
+ }
102
+
103
+ VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
104
+ return Backend_timer_loop(BACKEND(), interval);
105
+ }
106
+
107
+ VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
108
+ return Backend_wait_event(BACKEND(), raise);
109
+ }
110
+
111
+ VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
112
+ return Backend_wait_io(BACKEND(), io, write);
113
+ }
114
+
115
+ VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
116
+ return Backend_waitpid(BACKEND(), pid);
117
+ }
118
+
119
+ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
120
+ return Backend_write_m(argc, argv, BACKEND());
121
+ }
122
+
49
123
  void Init_Polyphony() {
50
124
  mPolyphony = rb_define_module("Polyphony");
51
125
 
52
126
  rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
53
127
 
128
+ // backend methods
129
+ rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
130
+ rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
131
+ rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
132
+ rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
133
+ rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
134
+ rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
135
+ rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
136
+ rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
137
+ rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
138
+ rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
139
+ rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
140
+ rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
141
+ rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
142
+ rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
143
+ rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
144
+ rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
145
+ rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
146
+ rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
147
+
54
148
  rb_define_global_function("snooze", Polyphony_snooze, 0);
55
149
  rb_define_global_function("suspend", Polyphony_suspend, 0);
56
150
 
@@ -23,9 +23,9 @@
23
23
  #define COND_TRACE(...) if (__tracing_enabled__) { TRACE(__VA_ARGS__); }
24
24
 
25
25
  // exceptions
26
- #define TEST_EXCEPTION(ret) (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
26
+ #define TEST_EXCEPTION(ret) (rb_obj_is_kind_of(ret, rb_eException) == Qtrue)
27
27
  #define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
28
- #define RAISE_IF_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { RAISE_EXCEPTION(ret); }
28
+ #define RAISE_IF_EXCEPTION(ret) if (rb_obj_is_kind_of(ret, rb_eException) == Qtrue) { RAISE_EXCEPTION(ret); }
29
29
  #define RAISE_IF_NOT_NIL(ret) if (ret != Qnil) { RAISE_EXCEPTION(ret); }
30
30
 
31
31
  // Fiber#transfer
@@ -89,6 +89,32 @@ void Runqueue_clear(VALUE self);
89
89
  long Runqueue_len(VALUE self);
90
90
  int Runqueue_empty_p(VALUE self);
91
91
 
92
+ #ifdef POLYPHONY_BACKEND_LIBEV
93
+ #define Backend_recv_loop Backend_read_loop
94
+ #define Backend_recv_feed_loop Backend_feed_loop
95
+ #endif
96
+
97
+ // Backend public interface
98
+
99
+ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
100
+ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
101
+ VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
102
+ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
103
+ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
104
+ VALUE Backend_read_loop(VALUE self, VALUE io);
105
+ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
106
+ VALUE Backend_recv_loop(VALUE self, VALUE io);
107
+ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
108
+ VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
109
+ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
110
+ VALUE Backend_sleep(VALUE self, VALUE duration);
111
+ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
112
+ VALUE Backend_timer_loop(VALUE self, VALUE interval);
113
+ VALUE Backend_wait_event(VALUE self, VALUE raise);
114
+ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
115
+ VALUE Backend_waitpid(VALUE self, VALUE pid);
116
+ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
117
+
92
118
  unsigned int Backend_pending_count(VALUE self);
93
119
  VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
94
120
  VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
@@ -247,7 +247,7 @@ VALUE Queue_size_m(VALUE self) {
247
247
  }
248
248
 
249
249
  void Init_Queue() {
250
- cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cData);
250
+ cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cObject);
251
251
  rb_define_alloc_func(cQueue, Queue_allocate);
252
252
 
253
253
  rb_define_method(cQueue, "initialize", Queue_initialize, -1);
@@ -101,7 +101,7 @@ int Runqueue_empty_p(VALUE self) {
101
101
  }
102
102
 
103
103
  void Init_Runqueue() {
104
- cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cData);
104
+ cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cObject);
105
105
  rb_define_alloc_func(cRunqueue, Runqueue_allocate);
106
106
 
107
107
  rb_define_method(cRunqueue, "initialize", Runqueue_initialize, 0);
@@ -16,7 +16,7 @@ if Object.constants.include?(:Reline)
16
16
  fiber.cancel
17
17
  end
18
18
  read_ios.each do |io|
19
- Thread.current.backend.wait_io(io, false)
19
+ Polyphony.backend_wait_io(io, false)
20
20
  return [io]
21
21
  end
22
22
  rescue Polyphony::Cancel
@@ -13,7 +13,7 @@ Mysql2::Client.prepend(Module.new do
13
13
 
14
14
  def query(sql, **options)
15
15
  super
16
- Thread.current.backend.wait_io(@io, false)
16
+ Polyphony.backend_wait_io(@io, false)
17
17
  async_result
18
18
  end
19
19
  end)
@@ -15,8 +15,8 @@ module ::PG
15
15
  res = conn.connect_poll
16
16
  case res
17
17
  when PGRES_POLLING_FAILED then raise Error, conn.error_message
18
- when PGRES_POLLING_READING then Thread.current.backend.wait_io(socket_io, false)
19
- when PGRES_POLLING_WRITING then Thread.current.backend.wait_io(socket_io, true)
18
+ when PGRES_POLLING_READING then Polyphony.backend_wait_io(socket_io, false)
19
+ when PGRES_POLLING_WRITING then Polyphony.backend_wait_io(socket_io, true)
20
20
  when PGRES_POLLING_OK then return conn.setnonblocking(true)
21
21
  end
22
22
  end
@@ -42,7 +42,7 @@ class ::PG::Connection
42
42
 
43
43
  def get_result(&block)
44
44
  while is_busy
45
- Thread.current.backend.wait_io(socket_io, false)
45
+ Polyphony.backend_wait_io(socket_io, false)
46
46
  consume_input
47
47
  end
48
48
  orig_get_result(&block)
@@ -59,7 +59,7 @@ class ::PG::Connection
59
59
 
60
60
  def block(_timeout = 0)
61
61
  while is_busy
62
- Thread.current.backend.wait_io(socket_io, false)
62
+ Polyphony.backend_wait_io(socket_io, false)
63
63
  consume_input
64
64
  end
65
65
  end
@@ -97,7 +97,7 @@ class ::PG::Connection
97
97
  return move_on_after(timeout) { wait_for_notify(&block) } if timeout
98
98
 
99
99
  while true
100
- Thread.current.backend.wait_io(socket_io, false)
100
+ Polyphony.backend_wait_io(socket_io, false)
101
101
  consume_input
102
102
  notice = notifies
103
103
  next unless notice