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 +4 -4
- data/.github/workflows/test.yaml +1 -1
- data/.github/workflows/valgrind.yaml +1 -1
- data/.gitignore +0 -3
- data/CHANGES.md +81 -0
- data/Rakefile +4 -29
- data/cool.io.gemspec +7 -1
- data/examples/dslified_echo_client.rb +1 -0
- data/examples/dslified_echo_server.rb +1 -0
- data/examples/echo_client.rb +3 -3
- data/ext/cool.io/buffer.c +0 -23
- data/ext/cool.io/cool.io.h +0 -16
- data/ext/cool.io/extconf.rb +0 -24
- data/ext/cool.io/iowatcher.c +0 -14
- data/ext/cool.io/stat_watcher.c +14 -8
- data/ext/cool.io/watcher.c +1 -1
- data/ext/libev/ev.c +39 -22
- data/ext/libev/ev_kqueue_stat.c +414 -0
- data/ext/libev/ev_vars.h +4 -0
- data/ext/libev/ev_wrap.h +4 -0
- data/lib/cool.io/version.rb +1 -1
- data/spec/fixtures/kqueue_stat_native.c +333 -0
- data/spec/fixtures/windows_stat_native.c +1 -5
- data/spec/kqueue_stat_native_spec.rb +103 -0
- data/spec/kqueue_stat_watcher_spec.rb +339 -0
- data/spec/stat_watcher_spec.rb +4 -5
- data/spec/timer_watcher_spec.rb +10 -1
- data/spec/windows_stat_native_spec.rb +2 -2
- metadata +14 -19
- data/appveyor.yml +0 -18
- data/examples/google.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 429eba65d9a49cece39e0c5315f02a72619581d58b2a40c5a3b4b54f5ed9450a
|
|
4
|
+
data.tar.gz: f2239fbc67d6a98f27c15e0a4acfe7136850eb2132b810cb60b10861902e81c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eeb064688621041ac6e3a68de8a7d4da6e873564bcbb7eb791cef2892801b67ea38d9ba7f7206dc0b541f2bc5ff63103779c090f8fb113f1d86d6902f3fc98dc
|
|
7
|
+
data.tar.gz: 95a1f57361191466510f22d0252a34c6b487af717bcc6209472c8f93e2da99b3607aa329cd912da2afd22aadb5df90b277ea0b54a17773b03c347e431fb7f309
|
data/.github/workflows/test.yaml
CHANGED
data/.gitignore
CHANGED
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 #{
|
|
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 "**/*.
|
|
61
|
-
CLEAN.exclude "vendor/**/*.
|
|
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
|
data/examples/echo_client.rb
CHANGED
|
@@ -17,16 +17,16 @@ class ClientConnection < Cool.io::TCPSocket
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def on_read(data)
|
|
20
|
-
|
|
20
|
+
puts "got #{data}"
|
|
21
21
|
close
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def on_resolve_failed
|
|
25
|
-
|
|
25
|
+
puts "DNS resolve failed"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def on_connect_failed
|
|
29
|
-
|
|
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
|
/*
|
data/ext/cool.io/cool.io.h
CHANGED
|
@@ -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
|
{
|
data/ext/cool.io/extconf.rb
CHANGED
|
@@ -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
|
|
data/ext/cool.io/iowatcher.c
CHANGED
|
@@ -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;
|
data/ext/cool.io/stat_watcher.c
CHANGED
|
@@ -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
|
|
37
|
-
*
|
|
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
|
|
81
|
-
* high performance file monitoring interfaces are used. On
|
|
82
|
-
*
|
|
83
|
-
* Windows watcher may also prevent renaming an ancestor
|
|
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
|
|
data/ext/cool.io/watcher.c
CHANGED
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);
|