cool.io 1.10.1 → 1.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84ec70f3ced722b0919a7e3348a6670e9d474343f8b831d9e942222a1edd0314
4
- data.tar.gz: b60d4526c1c799119c43db2ae0e0f3debb85cba85086a6c65868477398a88a66
3
+ metadata.gz: 429eba65d9a49cece39e0c5315f02a72619581d58b2a40c5a3b4b54f5ed9450a
4
+ data.tar.gz: f2239fbc67d6a98f27c15e0a4acfe7136850eb2132b810cb60b10861902e81c6
5
5
  SHA512:
6
- metadata.gz: 924f47393f2ae881e1afb914fa16bb67089840e8ef1c3599502919c5fa53263c06e0f6303d263ae376d8bff33da00ad9577b6549e3fc5128ead104a4f383e9d2
7
- data.tar.gz: 8929ec98ce4161507309610d762c5f22f7fe4b756c361902fb0e37afa69ee2d8adc788383866ec7c9d270b80f27a99e902c2ef5128804e3b9e86c2b46c6e0535
6
+ metadata.gz: eeb064688621041ac6e3a68de8a7d4da6e873564bcbb7eb791cef2892801b67ea38d9ba7f7206dc0b541f2bc5ff63103779c090f8fb113f1d86d6902f3fc98dc
7
+ data.tar.gz: 95a1f57361191466510f22d0252a34c6b487af717bcc6209472c8f93e2da99b3607aa329cd912da2afd22aadb5df90b277ea0b54a17773b03c347e431fb7f309
@@ -33,7 +33,7 @@ jobs:
33
33
  experimental: true
34
34
 
35
35
  steps:
36
- - uses: actions/checkout@v6
36
+ - uses: actions/checkout@v7
37
37
  - uses: ruby/setup-ruby@v1
38
38
  with:
39
39
  ruby-version: ${{matrix.ruby}}
@@ -27,7 +27,7 @@ jobs:
27
27
  experimental: true
28
28
 
29
29
  steps:
30
- - uses: actions/checkout@v6
30
+ - uses: actions/checkout@v7
31
31
  - uses: ruby/setup-ruby@v1
32
32
  with:
33
33
  ruby-version: ${{matrix.ruby}}
data/.gitignore CHANGED
@@ -19,9 +19,6 @@ rdoc
19
19
  pkg
20
20
  tmp
21
21
 
22
- ## RUBINIUS
23
- *.rbc
24
-
25
22
  ## PROJECT::SPECIFIC
26
23
  conftest.dSYM
27
24
 
data/CHANGES.md CHANGED
@@ -1,3 +1,84 @@
1
+ 1.11.0
2
+ ------
3
+
4
+ * Use kqueue notifications for StatWatcher on macOS, so that changes are reported promptly while polling remains as a backstop (#130)
5
+ * Fix Watcher#attached? returning 0 instead of true (#132)
6
+ * Fix the DSL examples and remove the HttpClient example (#133)
7
+ * Add bug tracker, changelog and source code links to the gem metadata and require MFA for gem owners (#138)
8
+ * Require Ruby 3.2 or later (#139, #140)
9
+
10
+ 1.10.1
11
+ ------
12
+
13
+ * Fix listen failing with EISCONN on Windows after a Loop with a StatWatcher is freed (#128)
14
+
15
+ 1.10.0
16
+ ------
17
+
18
+ * Use ReadDirectoryChangesW notifications for StatWatcher on Windows, so that changes are reported promptly while polling remains as a backstop (#109, #113)
19
+ * Fix quadratic polling, stop, notification and registration costs with many StatWatchers on Windows (#120, #121)
20
+ * Fix needless re-registration of Windows StatWatchers after the current directory changes (#122)
21
+ * Fix Windows StatWatcher missing changes in a directory recreated under the same name (#123)
22
+ * Speed up Windows StatWatcher name lookups (#124)
23
+ * Fix heap overflow in Buffer#read and Buffer#to_str on 64-bit Windows (#111)
24
+ * Fix memory leak when Buffer#clear is called repeatedly (#117)
25
+ * Fix DNS resolver accepting an A record shorter than its RDLENGTH (#107)
26
+ * Fix StatInfo fields truncated to 32 bits (#114)
27
+ * Fix StatInfo#blksize and StatInfo#blocks always being nil (#115)
28
+ * Fix IO and timer watcher reattachment (#112)
29
+ * Fix NameError when creating a Loop with skip_environment (#118)
30
+ * Fix SEGV when a Loop is created with no usable backend. It raises RuntimeError instead (#119)
31
+ * Fix Buffer#read documentation to match its argument handling (#116)
32
+ * Document that Loop.new raises RuntimeError when no backend is usable (#125)
33
+
34
+ 1.9.5
35
+ -----
36
+
37
+ * Fix 32-bit byte accounting in Buffer (#105)
38
+ * Fix FD_SETSIZE mismatch silently dropping watchers on Windows (#103)
39
+ * Fix dangling path pointer in StatWatcher under GC compaction (#98)
40
+ * Validate Buffer#read_frame argument to prevent SEGV (#97)
41
+ * Ignore IPv6 nameservers to prevent Socket::ResolutionError (#94)
42
+ * Fix Buffer.default_node_size documentation to match DEFAULT_NODE_SIZE (#99)
43
+
44
+ 1.9.4
45
+ -----
46
+
47
+ * Fix memory leak when detaching watchers (#91)
48
+
49
+ 1.9.3
50
+ -----
51
+
52
+ * Fix freeing of Buffer memory allocated with xmalloc (#84)
53
+
54
+ 1.9.2
55
+ -----
56
+
57
+ * Fix TypeError when processing a detached watcher (#88)
58
+
59
+ 1.9.1
60
+ -----
61
+
62
+ * Use typed data APIs for the extension objects (#85)
63
+ * Fix DNSResolver mutating the nameservers array given by the caller (commit 489ec55)
64
+
65
+ 1.9.0
66
+ -----
67
+
68
+ * Rename IO::Buffer to Coolio::Buffer and build it into the cool.io extension, since Ruby 3.1 added its own IO::Buffer (#82)
69
+
70
+ 1.8.1
71
+ -----
72
+
73
+ * Fix build error on Windows caused by incompatible pointer types (#81)
74
+
75
+ 1.8.0
76
+ -----
77
+
78
+ * Support Ruby 3.3 (#79)
79
+ * Fix build failure with compilers that reject incompatible function pointer types (#78)
80
+ * Fix fallback to the local loopback address when the hosts file has no localhost entry (#73)
81
+
1
82
  1.7.1
2
83
  -----
3
84
 
data/Rakefile CHANGED
@@ -4,18 +4,13 @@ require 'rake/clean'
4
4
  require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new
6
6
 
7
- RSpec::Core::RakeTask.new(:rcov) do |task|
8
- task.rcov = true
9
- end
10
-
11
7
  task :default => %w(compile spec)
12
8
 
13
9
  require 'rdoc/task'
10
+ require_relative 'lib/cool.io/version'
14
11
  Rake::RDocTask.new do |rdoc|
15
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
16
-
17
12
  rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = "cool.io #{version}"
13
+ rdoc.title = "cool.io #{Coolio::VERSION}"
19
14
  rdoc.rdoc_files.include('README*')
20
15
  rdoc.rdoc_files.include('lib/**/*.rb')
21
16
  end
@@ -24,28 +19,8 @@ require 'rake/extensiontask'
24
19
 
25
20
  spec = Gem::Specification.load("cool.io.gemspec")
26
21
 
27
- def configure_cross_compilation(ext)
28
- unless RUBY_PLATFORM =~ /mswin|mingw/
29
- ext.cross_compile = true
30
- ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
31
- end
32
- end
33
-
34
22
  Rake::ExtensionTask.new('cool.io_ext', spec) do |ext|
35
23
  ext.ext_dir = 'ext/cool.io'
36
- configure_cross_compilation(ext)
37
- end
38
-
39
- # Note that this rake-compiler-dock rake task dose not support bundle install(1) --path option.
40
- # Please use bundle install instead when you execute this rake task.
41
- namespace :build do
42
- desc 'Build gems for Windows per rake-compiler-dock'
43
- task :windows do
44
- require 'rake_compiler_dock'
45
- RakeCompilerDock.sh <<-CROSS
46
- bundle && bundle exec rake cross native gem RUBY_CC_VERSION='3.0.0:2.7.0:2.6.0:2.5.0:2.4.0'
47
- CROSS
48
- end
49
24
  end
50
25
 
51
26
  if RUBY_PLATFORM.include?('linux')
@@ -57,5 +32,5 @@ if RUBY_PLATFORM.include?('linux')
57
32
  end
58
33
  end
59
34
 
60
- CLEAN.include "**/*.rbc", "**/*.o", "**/*.so", "**/*.bundle"
61
- CLEAN.exclude "vendor/**/*.rbc", "vendor/**/*.o", "vendor/**/*.so", "vendor/**/*.bundle"
35
+ CLEAN.include "**/*.o", "**/*.so", "**/*.bundle"
36
+ CLEAN.exclude "vendor/**/*.o", "vendor/**/*.so", "vendor/**/*.bundle"
data/cool.io.gemspec CHANGED
@@ -6,6 +6,12 @@ Gem::Specification.new do |s|
6
6
  s.authors = ["Tony Arcieri", "Masahiro Nakagawa"]
7
7
  s.email = ["tony.arcieri@gmail.com", "repeatedly@gmail.com"]
8
8
  s.homepage = "https://github.com/socketry/cool.io"
9
+ s.metadata = {
10
+ "bug_tracker_uri" => "https://github.com/socketry/cool.io/issues",
11
+ "changelog_uri" => "https://github.com/socketry/cool.io/blob/main/CHANGES.md",
12
+ "source_code_uri" => "https://github.com/socketry/cool.io.git",
13
+ "rubygems_mfa_required" => "true",
14
+ }
9
15
  s.summary = "A cool framework for doing high performance I/O in Ruby"
10
16
  s.description = "Cool.io provides a high performance event framework for Ruby which uses the libev C library"
11
17
  s.extensions = ["ext/cool.io/extconf.rb"]
@@ -15,9 +21,9 @@ Gem::Specification.new do |s|
15
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
22
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
23
  s.require_paths = ["lib"]
24
+ s.required_ruby_version = ">= 3.2"
18
25
 
19
26
  s.add_development_dependency "rake-compiler", "~> 1.0"
20
- s.add_development_dependency "rake-compiler-dock", "~> 1.0"
21
27
  s.add_development_dependency "rspec", ">= 2.13.0"
22
28
  s.add_development_dependency "rdoc", ">= 3.6.0"
23
29
  end
@@ -2,6 +2,7 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  require 'rubygems'
4
4
  require 'cool.io'
5
+ require 'cool.io/dsl'
5
6
 
6
7
  ADDR = '127.0.0.1'
7
8
  PORT = 4321
@@ -2,6 +2,7 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  require 'rubygems'
4
4
  require 'cool.io'
5
+ require 'cool.io/dsl'
5
6
 
6
7
  ADDR = '127.0.0.1'
7
8
  PORT = 4321
@@ -17,16 +17,16 @@ class ClientConnection < Cool.io::TCPSocket
17
17
  end
18
18
 
19
19
  def on_read(data)
20
- print "got #{data}"
20
+ puts "got #{data}"
21
21
  close
22
22
  end
23
23
 
24
24
  def on_resolve_failed
25
- print "DNS resolve failed"
25
+ puts "DNS resolve failed"
26
26
  end
27
27
 
28
28
  def on_connect_failed
29
- print "connect failed, meaning our connection to their port was rejected"
29
+ puts "connect failed, meaning our connection to their port was rejected"
30
30
  end
31
31
 
32
32
  end
data/ext/cool.io/buffer.c CHANGED
@@ -20,13 +20,6 @@
20
20
  /* 1 GiB maximum buffer size */
21
21
  #define MAX_BUFFER_SIZE 0x40000000
22
22
 
23
- /* Macro for retrieving the file descriptor from an FPTR */
24
- #if !HAVE_RB_IO_T_FD
25
- #define FPTR_TO_FD(fptr) fileno(fptr->f)
26
- #else
27
- #define FPTR_TO_FD(fptr) fptr->fd
28
- #endif
29
-
30
23
  /* Default number of bytes in each node's buffer. Should be >= MTU */
31
24
  #define DEFAULT_NODE_SIZE 16384
32
25
  static size_t default_node_size = DEFAULT_NODE_SIZE;
@@ -414,22 +407,14 @@ Coolio_Buffer_read_from(VALUE self, VALUE io)
414
407
  {
415
408
  struct buffer *buf;
416
409
  ssize_t ret;
417
- #if defined(HAVE_RB_IO_T) || defined(HAVE_RB_IO_DESCRIPTOR)
418
410
  rb_io_t *fptr;
419
- #else
420
- OpenFile *fptr;
421
- #endif
422
411
 
423
412
  TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
424
413
  io = rb_convert_type(io, T_FILE, "IO", "to_io");
425
414
  GetOpenFile(io, fptr);
426
415
  rb_io_set_nonblock(fptr);
427
416
 
428
- #ifdef HAVE_RB_IO_DESCRIPTOR
429
417
  ret = buffer_read_from(buf, rb_io_descriptor(io));
430
- #else
431
- ret = buffer_read_from(buf, FPTR_TO_FD(fptr));
432
- #endif
433
418
  return ret == -1 ? Qnil : SSIZET2NUM(ret);
434
419
  }
435
420
 
@@ -445,22 +430,14 @@ static VALUE
445
430
  Coolio_Buffer_write_to(VALUE self, VALUE io)
446
431
  {
447
432
  struct buffer *buf;
448
- #if defined(HAVE_RB_IO_T) || defined(HAVE_RB_IO_DESCRIPTOR)
449
433
  rb_io_t *fptr;
450
- #else
451
- OpenFile *fptr;
452
- #endif
453
434
 
454
435
  TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
455
436
  io = rb_convert_type(io, T_FILE, "IO", "to_io");
456
437
  GetOpenFile(io, fptr);
457
438
  rb_io_set_nonblock(fptr);
458
439
 
459
- #ifdef HAVE_RB_IO_DESCRIPTOR
460
440
  return SSIZET2NUM(buffer_write_to(buf, rb_io_descriptor(io)));
461
- #else
462
- return SSIZET2NUM(buffer_write_to(buf, FPTR_TO_FD(fptr)));
463
- #endif
464
441
  }
465
442
 
466
443
  /*
@@ -8,23 +8,7 @@
8
8
  #define COOLIO_H
9
9
 
10
10
  #include "ruby.h"
11
- #if defined(HAVE_RUBY_IO_H)
12
11
  #include "ruby/io.h"
13
- #else
14
- #include "rubyio.h"
15
- #endif
16
-
17
- #ifdef GetReadFile
18
- #define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
19
- #else
20
-
21
- #if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
22
- #define FPTR_TO_FD(fptr) fileno(fptr->f)
23
- #else
24
- #define FPTR_TO_FD(fptr) fptr->fd
25
- #endif
26
-
27
- #endif
28
12
 
29
13
  struct Coolio_Event
30
14
  {
@@ -1,29 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
- libs = []
4
-
5
- $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
6
-
7
- have_func('rb_io_descriptor')
8
- have_func('rb_thread_blocking_region')
9
- have_func('rb_thread_call_without_gvl')
10
- have_func('rb_thread_alone')
11
- have_func('rb_str_set_len')
12
3
  have_library('rt', 'clock_gettime')
13
4
 
14
- have_library("c", "main")
15
- if have_macro("HAVE_RB_IO_T", "ruby/io.h")
16
- have_struct_member("rb_io_t", "fd", "ruby/io.h")
17
- end
18
-
19
- if have_header('ruby/io.h')
20
- $defs << '-DHAVE_RUBY_IO_H'
21
- end
22
-
23
- if have_header('ruby/thread.h')
24
- $defs << '-DHAVE_RUBY_THREAD_H'
25
- end
26
-
27
5
  if have_header('sys/select.h')
28
6
  $defs << '-DEV_USE_SELECT'
29
7
  end
@@ -61,8 +39,6 @@ if RUBY_PLATFORM =~ /solaris/
61
39
  $defs << '-D__EXTENSIONS__'
62
40
  end
63
41
 
64
- $LIBS << ' ' << libs.join(' ')
65
-
66
42
  dir_config('cool.io_ext')
67
43
  create_makefile('cool.io_ext')
68
44
 
@@ -5,11 +5,7 @@
5
5
  */
6
6
 
7
7
  #include "ruby.h"
8
- #if defined(HAVE_RUBY_IO_H)
9
8
  #include "ruby/io.h"
10
- #else
11
- #include "rubyio.h"
12
- #endif
13
9
 
14
10
  #include "ev_wrap.h"
15
11
 
@@ -86,17 +82,7 @@ static VALUE Coolio_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
86
82
  io = rb_convert_type(io, T_FILE, "IO", "to_io");
87
83
 
88
84
  watcher_data->dispatch_callback = Coolio_IOWatcher_dispatch_callback;
89
- #ifdef HAVE_RB_IO_DESCRIPTOR
90
85
  ev_io_init(&watcher_data->event_types.ev_io, Coolio_IOWatcher_libev_callback, rb_io_descriptor(io), events);
91
- #else
92
- #if defined(HAVE_RB_IO_T)
93
- rb_io_t *fptr;
94
- #else
95
- OpenFile *fptr;
96
- #endif
97
- GetOpenFile(io, fptr);
98
- ev_io_init(&watcher_data->event_types.ev_io, Coolio_IOWatcher_libev_callback, FPTR_TO_FD(fptr), events);
99
- #endif
100
86
  watcher_data->event_types.ev_io.data = (void *)self;
101
87
 
102
88
  return Qnil;
@@ -33,9 +33,8 @@ static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev
33
33
  static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents);
34
34
 
35
35
  /*
36
- * Coolio::StatWatcher lets you create either one-shot or periodic stats which
37
- * run within Coolio's event loop. It's useful for creating timeouts or
38
- * events which fire periodically.
36
+ * Coolio::StatWatcher monitors a path and calls on_change when its stat
37
+ * attributes change.
39
38
  **/
40
39
  void Init_coolio_stat_watcher()
41
40
  {
@@ -77,10 +76,18 @@ void Init_coolio_stat_watcher()
77
76
  * specified how often in seconds the path should be polled for changes.
78
77
  * Setting interval to zero uses an "automatic" value (typically around 5
79
78
  * seconds) which optimizes performance. Otherwise, values less than
80
- * 0.1 are not particularly meaningful. Where available (on Linux and Windows),
81
- * high performance file monitoring interfaces are used. On Windows, polling
82
- * remains necessary because notification timing is not guaranteed. An attached
83
- * Windows watcher may also prevent renaming an ancestor directory until detached.
79
+ * 0.1 are not particularly meaningful. Where available (on Linux, macOS and
80
+ * Windows), high performance file monitoring interfaces are used. On macOS
81
+ * and Windows, polling remains enabled for changes native notifications may
82
+ * miss. An attached Windows watcher may also prevent renaming an ancestor
83
+ * directory until detached.
84
+ *
85
+ * On macOS, each registered watcher uses one file descriptor for the path or
86
+ * an ancestor directory, plus one shared kqueue descriptor per loop. If the
87
+ * descriptor limit is reached, watchers fall back to polling.
88
+ *
89
+ * On macOS, construct the loop with :fork_check => true when continuing to
90
+ * use attached watchers in a forked child.
84
91
  */
85
92
  static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
86
93
  {
@@ -135,7 +142,6 @@ static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
135
142
  */
136
143
  static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop)
137
144
  {
138
- ev_tstamp interval, timeout;
139
145
  struct Coolio_Loop *loop_data;
140
146
  struct Coolio_Watcher *watcher_data;
141
147
 
@@ -271,7 +271,7 @@ static VALUE Coolio_Watcher_evloop(VALUE self)
271
271
  */
272
272
  static VALUE Coolio_Watcher_attached(VALUE self)
273
273
  {
274
- return Coolio_Watcher_evloop(self) != Qnil;
274
+ return Coolio_Watcher_evloop(self) != Qnil ? Qtrue : Qfalse;
275
275
  }
276
276
 
277
277
  /**
data/ext/libev/ev.c CHANGED
@@ -39,9 +39,7 @@
39
39
 
40
40
  /* ########## COOLIO PATCHERY HO! ########## */
41
41
  #include "ruby.h"
42
- #if defined(HAVE_RUBY_THREAD_H)
43
42
  #include "ruby/thread.h"
44
- #endif
45
43
  /* ######################################## */
46
44
 
47
45
  /* this big block deduces configuration from config.h */
@@ -342,6 +340,14 @@
342
340
  # endif
343
341
  #endif
344
342
 
343
+ #ifndef EV_USE_KQUEUE_STAT
344
+ # if EV_USE_KQUEUE && EV_STAT_ENABLE && defined __APPLE__ && defined __MACH__
345
+ # define EV_USE_KQUEUE_STAT 1
346
+ # else
347
+ # define EV_USE_KQUEUE_STAT 0
348
+ # endif
349
+ #endif
350
+
345
351
  #ifndef EV_PID_HASHSIZE
346
352
  # define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1
347
353
  #endif
@@ -1863,6 +1869,10 @@ typedef struct
1863
1869
  #if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
1864
1870
  static void win32_fs_destroy (EV_P);
1865
1871
  #endif
1872
+ #if EV_USE_KQUEUE_STAT
1873
+ static void kq_stat_fork (EV_P);
1874
+ static void kq_stat_destroy (EV_P);
1875
+ #endif
1866
1876
 
1867
1877
  #if EV_FEATURE_API
1868
1878
  # define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
@@ -2937,6 +2947,10 @@ loop_init (EV_P_ unsigned int flags) EV_THROW
2937
2947
  win32_fs = 0;
2938
2948
  win32_fs_disabled = (flags & EVFLAG_NOINOTIFY) != 0;
2939
2949
  #endif
2950
+ #if EV_USE_KQUEUE_STAT
2951
+ kq_stat = 0;
2952
+ kq_stat_disabled = (flags & EVFLAG_NOINOTIFY) != 0;
2953
+ #endif
2940
2954
  #if EV_USE_INOTIFY
2941
2955
  fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
2942
2956
  #endif
@@ -3008,6 +3022,9 @@ ev_loop_destroy (EV_P)
3008
3022
  #if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
3009
3023
  win32_fs_destroy (EV_A);
3010
3024
  #endif
3025
+ #if EV_USE_KQUEUE_STAT
3026
+ kq_stat_destroy (EV_A);
3027
+ #endif
3011
3028
 
3012
3029
  if (ev_is_active (&pipe_w))
3013
3030
  {
@@ -3110,6 +3127,9 @@ loop_fork (EV_P)
3110
3127
  #if EV_USE_INOTIFY
3111
3128
  infy_fork (EV_A);
3112
3129
  #endif
3130
+ #if EV_USE_KQUEUE_STAT
3131
+ kq_stat_fork (EV_A);
3132
+ #endif
3113
3133
 
3114
3134
  #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
3115
3135
  if (ev_is_active (&pipe_w) && postfork != 2)
@@ -3602,7 +3622,6 @@ time_update (EV_P_ ev_tstamp max_block)
3602
3622
  }
3603
3623
 
3604
3624
  /* ########## COOLIO PATCHERY HO! ########## */
3605
- #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3606
3625
  struct ev_poll_args {
3607
3626
  struct ev_loop *loop;
3608
3627
  ev_tstamp waittime;
@@ -3616,16 +3635,13 @@ VALUE ev_backend_poll(void *ptr)
3616
3635
  backend_poll (EV_A_ args->waittime);
3617
3636
  return Qnil;
3618
3637
  }
3619
- #endif
3620
3638
  /* ######################################## */
3621
3639
 
3622
3640
  int
3623
3641
  ev_run (EV_P_ int flags)
3624
3642
  {
3625
3643
  /* ########## COOLIO PATCHERY HO! ########## */
3626
- #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3627
3644
  struct ev_poll_args poll_args;
3628
- #endif
3629
3645
  /* ######################################## */
3630
3646
 
3631
3647
  #if EV_FEATURE_API
@@ -3786,25 +3802,9 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3786
3802
  #######################################################################
3787
3803
  */
3788
3804
 
3789
- /*
3790
- simulate to rb_thread_call_without_gvl using rb_theread_blocking_region.
3791
- https://github.com/brianmario/mysql2/blob/master/ext/mysql2/client.h#L8
3792
- */
3793
-
3794
- #ifndef HAVE_RB_THREAD_CALL_WITHOUT_GVL
3795
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
3796
- #define rb_thread_call_without_gvl(func, data1, ubf, data2) \
3797
- rb_thread_blocking_region((rb_blocking_function_t *)func, data1, ubf, data2)
3798
- #endif
3799
- #endif
3800
-
3801
- #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3802
3805
  poll_args.loop = loop;
3803
3806
  poll_args.waittime = waittime;
3804
3807
  rb_thread_call_without_gvl((void *)ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
3805
- #else
3806
- backend_poll (EV_A_ waittime);
3807
- #endif
3808
3808
  /*
3809
3809
  ############################# END PATCHERY ############################
3810
3810
  */
@@ -4366,6 +4366,9 @@ noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
4366
4366
  #if defined(_WIN32) && EV_ASYNC_ENABLE
4367
4367
  # include "ev_win32_stat.c"
4368
4368
  #endif
4369
+ #if EV_USE_KQUEUE_STAT
4370
+ # include "ev_kqueue_stat.c"
4371
+ #endif
4369
4372
 
4370
4373
  #if EV_USE_INOTIFY
4371
4374
 
@@ -4648,6 +4651,10 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
4648
4651
  win32_fs_add (EV_A_ w, 1); /* retry missing parents or failed directory handles */
4649
4652
  #endif
4650
4653
 
4654
+ #if EV_USE_KQUEUE_STAT
4655
+ kq_stat_poll (EV_A_ w, revents);
4656
+ #endif
4657
+
4651
4658
  ev_statdata prev = w->attr;
4652
4659
  ev_stat_stat (EV_A_ w);
4653
4660
 
@@ -4685,6 +4692,10 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
4685
4692
  }
4686
4693
  #endif
4687
4694
 
4695
+ #if EV_USE_KQUEUE_STAT
4696
+ kq_stat_refresh (EV_A_ w);
4697
+ #endif
4698
+
4688
4699
  ev_feed_event (EV_A_ w, EV_STAT);
4689
4700
  }
4690
4701
  }
@@ -4721,6 +4732,9 @@ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
4721
4732
  win32_fs_add (EV_A_ w, 0);
4722
4733
  stat_timer_cb (EV_A_ &w->timer, 0); /* close the stat/registration race */
4723
4734
  #endif
4735
+ #if EV_USE_KQUEUE_STAT
4736
+ kq_stat_start (EV_A_ w);
4737
+ #endif
4724
4738
 
4725
4739
  EV_FREQUENT_CHECK;
4726
4740
  }
@@ -4737,6 +4751,9 @@ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
4737
4751
  #if defined(_WIN32) && EV_ASYNC_ENABLE
4738
4752
  win32_fs_del (EV_A_ w);
4739
4753
  #endif
4754
+ #if EV_USE_KQUEUE_STAT
4755
+ kq_stat_del (EV_A_ w);
4756
+ #endif
4740
4757
 
4741
4758
  #if EV_USE_INOTIFY
4742
4759
  infy_del (EV_A_ w);