polyphony 0.72 → 0.75

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +15 -11
  3. data/.github/workflows/test_io_uring.yml +32 -0
  4. data/.gitignore +3 -1
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile.lock +16 -13
  7. data/bin/pdbg +0 -0
  8. data/bin/polyphony-debug +0 -0
  9. data/bin/stress.rb +0 -0
  10. data/bin/test +0 -0
  11. data/docs/api-reference/exception.md +5 -1
  12. data/examples/core/ring.rb +29 -0
  13. data/ext/polyphony/backend_common.c +90 -12
  14. data/ext/polyphony/backend_common.h +9 -1
  15. data/ext/polyphony/backend_io_uring.c +257 -134
  16. data/ext/polyphony/backend_io_uring_context.c +1 -0
  17. data/ext/polyphony/backend_io_uring_context.h +2 -1
  18. data/ext/polyphony/backend_libev.c +33 -29
  19. data/ext/polyphony/event.c +5 -2
  20. data/ext/polyphony/extconf.rb +1 -0
  21. data/ext/polyphony/polyphony.c +11 -1
  22. data/ext/polyphony/polyphony.h +9 -2
  23. data/ext/polyphony/queue.c +10 -5
  24. data/ext/polyphony/runqueue_ring_buffer.c +3 -1
  25. data/ext/polyphony/socket_extensions.c +5 -2
  26. data/ext/polyphony/thread.c +1 -1
  27. data/lib/polyphony/{extensions → core}/debug.rb +0 -0
  28. data/lib/polyphony/core/global_api.rb +0 -3
  29. data/lib/polyphony/extensions/exception.rb +45 -0
  30. data/lib/polyphony/extensions/fiber.rb +85 -4
  31. data/lib/polyphony/extensions/{core.rb → kernel.rb} +0 -73
  32. data/lib/polyphony/extensions/openssl.rb +5 -1
  33. data/lib/polyphony/extensions/process.rb +19 -0
  34. data/lib/polyphony/extensions/socket.rb +12 -6
  35. data/lib/polyphony/extensions/thread.rb +9 -3
  36. data/lib/polyphony/extensions/timeout.rb +10 -0
  37. data/lib/polyphony/extensions.rb +9 -0
  38. data/lib/polyphony/version.rb +1 -1
  39. data/lib/polyphony.rb +4 -4
  40. data/test/helper.rb +0 -5
  41. data/test/test_backend.rb +3 -5
  42. data/test/test_global_api.rb +21 -12
  43. data/test/test_io.rb +2 -2
  44. data/test/test_kernel.rb +2 -2
  45. data/test/test_process_supervision.rb +1 -1
  46. data/test/test_signal.rb +20 -1
  47. data/test/test_socket.rb +35 -2
  48. data/test/test_thread.rb +1 -1
  49. data/test/test_thread_pool.rb +1 -1
  50. data/test/test_throttler.rb +3 -3
  51. data/test/test_timer.rb +1 -1
  52. data/test/test_trace.rb +7 -1
  53. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2af189faeecbe2eecb367a7400005306ab74370e56c61de1d703edd40d851d92
4
- data.tar.gz: c0888b10d03b9bf29f1d10a41b0050231db655c587d06035039b4c09e1c68baa
3
+ metadata.gz: 25015dd770af4d3b375af0625cfe9fe98becb328a0e77abb3101be2580279a7c
4
+ data.tar.gz: e2227ea3fa7d3ec04f5b580afdc92b9d7aacbab76b9e17dd0b86fb5e4e5b6a6f
5
5
  SHA512:
6
- metadata.gz: b86fd5682ce52e635658a8d620031f8ae841ef5f7876d6239f74772d8f700054eb3bb7732488e246433a91e5ab4279479c6f18bb0d1a154172d90f351ab8149e
7
- data.tar.gz: 713ba61a64ef73c5c16971bd0d678d6575b7bd37062a29348f02ec8e0578821d7ec41f826f1868cd017bede9c70d47192e19a0217469b331f17ff66afac21054
6
+ metadata.gz: 967f6aa30621aae39dafdb587c28e1c0ec96685fc82972adb19fb50de7adfaaa42ce861c0f941f85ad536e29b459251d22c34a6bd96f8fc89f23dd4c0ecac47a
7
+ data.tar.gz: b3d6884d859c4eb61ca1d8bc8d1b727a5bf66c6c1af5280896264414bf14654650a1d8bcf3a6b744d235f5dd435e9231a0e047f95a17bfb7ce1642791c347c05
@@ -7,25 +7,29 @@ jobs:
7
7
  strategy:
8
8
  fail-fast: false
9
9
  matrix:
10
- os: [ubuntu-latest, ubuntu-18.04, macos-10.15]
11
- ruby: [2.6, 2.7, 3.0]
10
+ os: [ubuntu-latest, macos-latest]
11
+ ruby: ['2.7', '3.0', '3.1', 'head']
12
12
 
13
13
  name: >-
14
14
  ${{matrix.os}}, ${{matrix.ruby}}
15
15
 
16
16
  runs-on: ${{matrix.os}}
17
+
18
+ env:
19
+ POLYPHONY_USE_LIBEV: "1"
20
+
17
21
  steps:
18
- - uses: actions/checkout@v1
19
- - uses: actions/setup-ruby@v1
22
+ - name: Setup OS
23
+ uses: actions/checkout@v1
24
+ - name: Setup Ruby
25
+ uses: ruby/setup-ruby@v1
20
26
  with:
21
27
  ruby-version: ${{matrix.ruby}}
22
- - name: Install dependencies
23
- run: |
24
- gem install bundler
25
- bundle install
26
- - name: Show Linux kernel version
27
- run: uname -r
28
+ bundler-cache: true # 'bundle install' and cache
29
+ cache-version: 2
30
+ - name: Kernel version
31
+ run: uname -a
28
32
  - name: Compile C-extension
29
- run: POLYPHONY_USE_LIBEV=1 bundle exec rake compile
33
+ run: bundle exec rake compile
30
34
  - name: Run tests
31
35
  run: bundle exec rake test
@@ -0,0 +1,32 @@
1
+ name: Tests with io_uring
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest]
11
+ ruby: [2.6, 2.7, 3.0]
12
+
13
+ name: >-
14
+ ${{matrix.os}}, ${{matrix.ruby}}
15
+
16
+ runs-on: ${{matrix.os}}
17
+ steps:
18
+ - uses: actions/checkout@v1
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{matrix.ruby}}
22
+ bundler-cache: true # 'bundle install' and cache
23
+ - name: Install dependencies
24
+ run: |
25
+ gem install bundler
26
+ bundle install
27
+ - name: Show Linux kernel version
28
+ run: uname -a
29
+ - name: Compile C-extension
30
+ run: bundle exec rake compile
31
+ - name: Run tests
32
+ run: bundle exec rake test
data/.gitignore CHANGED
@@ -58,4 +58,6 @@ lib/*.so
58
58
  _site
59
59
  .sass-cache
60
60
 
61
- log
61
+ log
62
+
63
+ .ruby-version
data/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ ## 0.75 2022-02-04
2
+
3
+ - Fix handling of MoveOn on main fiber of forked process
4
+ - Ensure SSLSocket underlying socket is in nonblocking mode
5
+ - Add `Polyphony.backend_verify_blocking_mode` API
6
+ - Fix address resolution for hostnames with IPv6 address
7
+ - Improve behaviour of OOB fiber
8
+ - Include caller in `fiber_switchpoint` trace
9
+
10
+ ## 0.74 2022-02-01
11
+
12
+ - Add support for IPv6 (#69)
13
+ - Override TCPSocket.open
14
+
15
+ ## 0.73.1 2021-12-17
16
+
17
+ - Fix Gemfile.lock
18
+
19
+ ## 0.73 2021-12-16
20
+
21
+ - Refactor core extensions into separate files for each class
22
+ - Improve compatibility with Ruby 3.1
23
+ - Improve accuracy of `timer_loop`
24
+
1
25
  ## 0.72 2021-11-22
2
26
 
3
27
  - Add support for supervising added child fibers
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.72)
4
+ polyphony (0.75)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -14,12 +14,12 @@ GEM
14
14
  httparty (0.17.1)
15
15
  mime-types (~> 3.0)
16
16
  multi_xml (>= 0.5.2)
17
- json (2.5.1)
18
- localhost (1.1.8)
17
+ json (2.6.1)
18
+ localhost (1.1.9)
19
19
  method_source (1.0.0)
20
- mime-types (3.3.1)
20
+ mime-types (3.4.1)
21
21
  mime-types-data (~> 3.2015)
22
- mime-types-data (3.2021.0704)
22
+ mime-types-data (3.2022.0105)
23
23
  minitest (5.14.4)
24
24
  minitest-reporters (1.4.2)
25
25
  ansi
@@ -28,17 +28,17 @@ GEM
28
28
  ruby-progressbar
29
29
  msgpack (1.4.2)
30
30
  multi_xml (0.6.0)
31
- parallel (1.20.1)
32
- parser (3.0.2.0)
31
+ parallel (1.21.0)
32
+ parser (3.1.0.0)
33
33
  ast (~> 2.4.1)
34
34
  pry (0.13.1)
35
35
  coderay (~> 1.1)
36
36
  method_source (~> 1.0)
37
- rainbow (3.0.0)
37
+ rainbow (3.1.1)
38
38
  rake (13.0.6)
39
39
  rake-compiler (1.1.1)
40
40
  rake
41
- regexp_parser (2.1.1)
41
+ regexp_parser (2.2.0)
42
42
  rexml (3.2.5)
43
43
  rubocop (0.85.1)
44
44
  parallel (~> 1.10)
@@ -49,7 +49,7 @@ GEM
49
49
  rubocop-ast (>= 0.0.3)
50
50
  ruby-progressbar (~> 1.7)
51
51
  unicode-display_width (>= 1.4.0, < 2.0)
52
- rubocop-ast (1.8.0)
52
+ rubocop-ast (1.15.1)
53
53
  parser (>= 3.0.1.1)
54
54
  ruby-progressbar (1.11.0)
55
55
  simplecov (0.17.1)
@@ -57,10 +57,13 @@ GEM
57
57
  json (>= 1.8, < 3)
58
58
  simplecov-html (~> 0.10.0)
59
59
  simplecov-html (0.10.2)
60
- unicode-display_width (1.7.0)
60
+ unicode-display_width (1.8.0)
61
61
 
62
62
  PLATFORMS
63
- ruby
63
+ universal-darwin
64
+ universal-freebsd
65
+ universal-linux
66
+ universal-unknown
64
67
 
65
68
  DEPENDENCIES
66
69
  httparty (= 0.17.1)
@@ -75,4 +78,4 @@ DEPENDENCIES
75
78
  simplecov (= 0.17.1)
76
79
 
77
80
  BUNDLED WITH
78
- 2.2.26
81
+ 2.3.3
data/bin/pdbg CHANGED
File without changes
data/bin/polyphony-debug CHANGED
File without changes
data/bin/stress.rb CHANGED
File without changes
data/bin/test CHANGED
File without changes
@@ -3,15 +3,19 @@ layout: page
3
3
  title: ::Exception
4
4
  parent: API Reference
5
5
  permalink: /api-reference/exception/
6
+ source_url: https://github.com/digital-fabric/polyphony/blob/master/lib/polyphony/extensions/core.rb
7
+ ruby_docs_url: https://rubyapi.org/3.0/o/exception
6
8
  ---
7
9
  # ::Exception
8
10
 
9
- [Ruby core Exception documentation](https://ruby-doc.org/core-2.7.0/Exception.html)
11
+ [Ruby core Exception documentation](https://rubyapi.org/3.0/o/exception)
10
12
 
11
13
  The core `Exception` class is enhanced to provide a better backtrace that takes
12
14
  into account the fiber hierarchy. In addition, a `source_fiber` attribute allows
13
15
  tracking the fiber from which an uncaught exception was propagated.
14
16
 
17
+
18
+
15
19
  ## Class Methods
16
20
 
17
21
  ## Instance methods
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ M = 100
7
+ N = 10000
8
+
9
+ GC.disable
10
+
11
+ def monotonic_clock
12
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
13
+ end
14
+
15
+ def spin_proc(next_fiber)
16
+ spin_loop { next_fiber << receive }
17
+ end
18
+
19
+ last = Fiber.current
20
+ N.times { last = spin_proc(last) }
21
+
22
+ snooze
23
+ t0 = monotonic_clock
24
+ M.times do
25
+ last << 'hello'
26
+ receive
27
+ end
28
+ elapsed = monotonic_clock - t0
29
+ puts "M=#{M} N=#{N} elapsed: #{elapsed}"
@@ -64,7 +64,8 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
64
64
  unsigned int idle_tasks_run_count = 0;
65
65
 
66
66
  base->switch_count++;
67
- COND_TRACE(base, 2, SYM_fiber_switchpoint, current_fiber);
67
+ if (SHOULD_TRACE(base))
68
+ TRACE(base, 3, SYM_fiber_switchpoint, current_fiber, CALLER());
68
69
 
69
70
  while (1) {
70
71
  next = runqueue_shift(&base->runqueue);
@@ -106,14 +107,14 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
106
107
 
107
108
  void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_base *base, VALUE fiber, VALUE value, int prioritize) {
108
109
  int already_runnable;
110
+ runqueue_t *runqueue;
109
111
 
110
112
  if (rb_fiber_alive_p(fiber) != Qtrue) return;
111
113
  already_runnable = rb_ivar_get(fiber, ID_ivar_runnable) != Qnil;
112
114
 
113
115
  COND_TRACE(base, 4, SYM_fiber_schedule, fiber, value, prioritize ? Qtrue : Qfalse);
114
116
 
115
- runqueue_t *runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ?
116
- &base->parked_runqueue : &base->runqueue;
117
+ runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ? &base->parked_runqueue : &base->runqueue;
117
118
 
118
119
  (prioritize ? runqueue_unshift : runqueue_push)(runqueue, fiber, value, already_runnable);
119
120
  if (!already_runnable) {
@@ -202,11 +203,40 @@ inline rb_encoding* io_read_encoding(rb_io_t *fptr) {
202
203
  }
203
204
 
204
205
  inline VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
205
- OBJ_TAINT(str);
206
206
  rb_enc_associate(str, io_read_encoding(fptr));
207
207
  return str;
208
208
  }
209
209
 
210
+ static inline void free_io_buffer(rb_io_buffer_t *buf)
211
+ {
212
+ if (buf->ptr) {
213
+ ruby_xfree(buf->ptr);
214
+ buf->ptr = NULL;
215
+ }
216
+ }
217
+
218
+ static inline void clear_codeconv(rb_io_t *fptr) {
219
+ if (fptr->readconv) {
220
+ rb_econv_close(fptr->readconv);
221
+ fptr->readconv = NULL;
222
+ }
223
+ free_io_buffer(&fptr->cbuf);
224
+
225
+ if (fptr->writeconv) {
226
+ rb_econv_close(fptr->writeconv);
227
+ fptr->writeconv = NULL;
228
+ }
229
+ fptr->writeconv_initialized = 0;
230
+ }
231
+
232
+ void fptr_finalize(rb_io_t *fptr) {
233
+ fptr->fd = -1;
234
+ fptr->stdio_file = 0;
235
+ free_io_buffer(&fptr->rbuf);
236
+ free_io_buffer(&fptr->wbuf);
237
+ clear_codeconv(fptr);
238
+ }
239
+
210
240
  //////////////////////////////////////////////////////////////////////
211
241
  //////////////////////////////////////////////////////////////////////
212
242
 
@@ -239,13 +269,25 @@ inline void rectify_io_file_pos(rb_io_t *fptr) {
239
269
 
240
270
  inline double current_time() {
241
271
  struct timespec ts;
272
+ double t;
273
+ uint64_t ns;
274
+
242
275
  clock_gettime(CLOCK_MONOTONIC, &ts);
243
- long long ns = ts.tv_sec;
276
+ ns = ts.tv_sec;
244
277
  ns = ns * 1e9 + ts.tv_nsec;
245
- double t = ns;
278
+ t = ns;
246
279
  return t / 1e9;
247
280
  }
248
281
 
282
+ inline uint64_t current_time_ns() {
283
+ struct timespec ts;
284
+ uint64_t ns;
285
+
286
+ clock_gettime(CLOCK_MONOTONIC, &ts);
287
+ ns = ts.tv_sec;
288
+ return ns * 1e9 + ts.tv_nsec;
289
+ }
290
+
249
291
  inline VALUE backend_timeout_exception(VALUE exception) {
250
292
  if (rb_obj_is_kind_of(exception, rb_cArray) == Qtrue)
251
293
  return rb_funcall(rb_ary_entry(exception, 0), ID_new, 1, rb_ary_entry(exception, 1));
@@ -270,6 +312,9 @@ VALUE Backend_timeout_ensure_safe(VALUE arg) {
270
312
  static VALUE empty_string = Qnil;
271
313
 
272
314
  VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
315
+ VALUE joined;
316
+ VALUE result;
317
+
273
318
  switch (RARRAY_LEN(ary)) {
274
319
  case 0:
275
320
  return Qnil;
@@ -280,14 +325,16 @@ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
280
325
  empty_string = rb_str_new_literal("");
281
326
  rb_global_variable(&empty_string);
282
327
  }
283
- VALUE joined = rb_ary_join(ary, empty_string);
284
- VALUE result = Backend_send(self, io, joined, flags);
328
+ joined = rb_ary_join(ary, empty_string);
329
+ result = Backend_send(self, io, joined, flags);
285
330
  RB_GC_GUARD(joined);
286
331
  return result;
287
332
  }
288
333
  }
289
334
 
290
335
  inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
336
+ int flags;
337
+ int is_nonblocking;
291
338
  VALUE blocking_mode = rb_ivar_get(io, ID_ivar_blocking_mode);
292
339
  if (blocking == blocking_mode) return;
293
340
 
@@ -297,9 +344,9 @@ inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
297
344
  if (blocking != Qtrue)
298
345
  rb_w32_set_nonblock(fptr->fd);
299
346
  #elif defined(F_GETFL)
300
- int flags = fcntl(fptr->fd, F_GETFL);
347
+ flags = fcntl(fptr->fd, F_GETFL);
301
348
  if (flags == -1) return;
302
- int is_nonblocking = flags & O_NONBLOCK;
349
+ is_nonblocking = flags & O_NONBLOCK;
303
350
 
304
351
  if (blocking == Qtrue) {
305
352
  if (!is_nonblocking) return;
@@ -313,12 +360,14 @@ inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
313
360
  }
314
361
 
315
362
  inline void backend_run_idle_tasks(struct Backend_base *base) {
363
+ double now;
364
+
316
365
  if (base->idle_proc != Qnil)
317
366
  rb_funcall(base->idle_proc, ID_call, 0);
318
367
 
319
368
  if (base->idle_gc_period == 0) return;
320
369
 
321
- double now = current_time();
370
+ now = current_time();
322
371
  if (now - base->idle_gc_last_time < base->idle_gc_period) return;
323
372
 
324
373
  base->idle_gc_last_time = now;
@@ -367,6 +416,13 @@ VALUE Backend_stats(VALUE self) {
367
416
  return stats;
368
417
  }
369
418
 
419
+ VALUE Backend_verify_blocking_mode(VALUE self, VALUE io, VALUE blocking) {
420
+ rb_io_t *fptr;
421
+ GetOpenFile(io, fptr);
422
+ io_verify_blocking_mode(fptr, io, blocking);
423
+ return self;
424
+ }
425
+
370
426
  void backend_setup_stats_symbols() {
371
427
  SYM_runqueue_size = ID2SYM(rb_intern("runqueue_size"));
372
428
  SYM_runqueue_length = ID2SYM(rb_intern("runqueue_length"));
@@ -383,4 +439,26 @@ void backend_setup_stats_symbols() {
383
439
  rb_global_variable(&SYM_switch_count);
384
440
  rb_global_variable(&SYM_poll_count);
385
441
  rb_global_variable(&SYM_pending_ops);
386
- }
442
+ }
443
+
444
+ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr) {
445
+ VALUE port_string;
446
+ struct addrinfo hints;
447
+ struct addrinfo *addrinfo_result;
448
+ int ret;
449
+
450
+ memset(&hints, 0, sizeof(struct addrinfo));
451
+ hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
452
+ hints.ai_socktype = SOCK_STREAM;
453
+
454
+ port_string = rb_funcall(port, ID_to_s, 0);
455
+ ret = getaddrinfo(StringValueCStr(host), StringValueCStr(port_string), &hints, &addrinfo_result);
456
+ RB_GC_GUARD(port_string);
457
+ if (ret != 0) {
458
+ VALUE msg = rb_str_new2(gai_strerror(ret));
459
+ rb_funcall(rb_mKernel, ID_raise, 1, msg);
460
+ RB_GC_GUARD(msg);
461
+ }
462
+ *ai_addr = addrinfo_result->ai_addr;
463
+ return addrinfo_result->ai_addrlen;
464
+ }
@@ -1,6 +1,11 @@
1
1
  #ifndef BACKEND_COMMON_H
2
2
  #define BACKEND_COMMON_H
3
3
 
4
+ #include <sys/types.h>
5
+ #include <arpa/inet.h>
6
+ #include <netinet/in.h>
7
+ #include <netdb.h>
8
+
4
9
  #include "ruby.h"
5
10
  #include "ruby/io.h"
6
11
  #include "runqueue.h"
@@ -68,6 +73,7 @@ void io_shrink_read_string(VALUE str, long n);
68
73
  void io_set_read_length(VALUE str, long n, int shrinkable);
69
74
  rb_encoding* io_read_encoding(rb_io_t *fptr);
70
75
  VALUE io_enc_str(VALUE str, rb_io_t *fptr);
76
+ void fptr_finalize(rb_io_t *fptr);
71
77
 
72
78
  //////////////////////////////////////////////////////////////////////
73
79
  //////////////////////////////////////////////////////////////////////
@@ -82,7 +88,6 @@ VALUE backend_snooze();
82
88
  shrinkable = io_setstrbuf(&str, len); \
83
89
  buf = RSTRING_PTR(str); \
84
90
  total = 0; \
85
- OBJ_TAINT(str); \
86
91
  }
87
92
 
88
93
  #define READ_LOOP_YIELD_STR() { \
@@ -101,13 +106,16 @@ VALUE backend_snooze();
101
106
 
102
107
  void rectify_io_file_pos(rb_io_t *fptr);
103
108
  double current_time();
109
+ uint64_t current_time_ns();
104
110
  VALUE backend_timeout_exception(VALUE exception);
105
111
  VALUE Backend_timeout_ensure_safe(VALUE arg);
106
112
  VALUE Backend_timeout_ensure_safe(VALUE arg);
107
113
  VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
108
114
  VALUE Backend_stats(VALUE self);
115
+ VALUE Backend_verify_blocking_mode(VALUE self, VALUE io, VALUE blocking);
109
116
  void backend_run_idle_tasks(struct Backend_base *base);
110
117
  void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking);
111
118
  void backend_setup_stats_symbols();
119
+ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr);
112
120
 
113
121
  #endif /* BACKEND_COMMON_H */