cool.io 1.9.0 → 1.9.5
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 +8 -19
- data/.github/workflows/valgrind.yaml +44 -0
- data/Rakefile +6 -19
- data/cool.io.gemspec +1 -3
- data/ext/cool.io/buffer.c +82 -64
- data/ext/cool.io/cool.io.h +9 -0
- data/ext/cool.io/extconf.rb +0 -1
- data/ext/cool.io/iowatcher.c +1 -1
- data/ext/cool.io/loop.c +49 -29
- data/ext/cool.io/stat_watcher.c +19 -6
- data/ext/cool.io/timer_watcher.c +5 -5
- data/ext/cool.io/watcher.c +38 -13
- data/ext/cool.io/watcher.h +14 -15
- data/ext/libev/ev.c +7 -1
- data/ext/libev/ev_select.c +10 -0
- data/gems.rb +4 -0
- data/lib/cool.io/dns_resolver.rb +53 -9
- data/lib/cool.io/version.rb +2 -2
- data/libev_win_select.diff +25 -9
- data/spec/async_watcher_spec.rb +3 -1
- data/spec/detach_race_condition_spec.rb +117 -0
- data/spec/dns_spec.rb +186 -0
- data/spec/iobuffer_spec.rb +31 -0
- data/spec/stat_watcher_spec.rb +31 -1
- data/spec/tcp_server_spec.rb +28 -4
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3da0843b8a62fd01aab297ce31f885a5856b4326bef2fb3c90d363f9576fe9a3
|
|
4
|
+
data.tar.gz: d073dd104500ccc2c1b62411c8f02c083df004353f9d2798ccf8ae41166effbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3f2fab2151abdbd3e0762aa04675cab8b4d196990227bf5d068f12360a62c87e669480f50e70b47b289a9c0f29deeddb28836590422faafe5d0a5ecaf6173fb
|
|
7
|
+
data.tar.gz: 233ea14784f4390b6b1f1b8fb131d5b1d20d14d0b78f9f1fd3b39f89bd25d34be505267d23d1b5647be2febcd5216e33a459c0e135ee49737334a06a0626bb47
|
data/.github/workflows/test.yaml
CHANGED
|
@@ -5,9 +5,6 @@ on: [push, pull_request]
|
|
|
5
5
|
permissions:
|
|
6
6
|
contents: read
|
|
7
7
|
|
|
8
|
-
env:
|
|
9
|
-
CONSOLE_OUTPUT: XTerm
|
|
10
|
-
|
|
11
8
|
jobs:
|
|
12
9
|
test:
|
|
13
10
|
name: ${{matrix.ruby}} on ${{matrix.os}}
|
|
@@ -20,35 +17,27 @@ jobs:
|
|
|
20
17
|
os:
|
|
21
18
|
- ubuntu
|
|
22
19
|
- macos
|
|
23
|
-
- windows
|
|
24
20
|
|
|
25
21
|
ruby:
|
|
26
|
-
- "3.0"
|
|
27
|
-
- "3.1"
|
|
28
22
|
- "3.2"
|
|
29
23
|
- "3.3"
|
|
30
|
-
- "
|
|
24
|
+
- "3.4"
|
|
25
|
+
- "4.0"
|
|
31
26
|
|
|
32
27
|
experimental: [false]
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# - os: ubuntu
|
|
39
|
-
# ruby: jruby
|
|
40
|
-
# experimental: true
|
|
41
|
-
# - os: ubuntu
|
|
42
|
-
# ruby: head
|
|
43
|
-
# experimental: true
|
|
29
|
+
include:
|
|
30
|
+
- os: ubuntu
|
|
31
|
+
ruby: head
|
|
32
|
+
experimental: true
|
|
44
33
|
|
|
45
34
|
steps:
|
|
46
|
-
- uses: actions/checkout@
|
|
35
|
+
- uses: actions/checkout@v6
|
|
47
36
|
- uses: ruby/setup-ruby@v1
|
|
48
37
|
with:
|
|
49
38
|
ruby-version: ${{matrix.ruby}}
|
|
50
39
|
bundler-cache: true
|
|
51
40
|
|
|
52
41
|
- name: Run tests
|
|
53
|
-
timeout-minutes:
|
|
42
|
+
timeout-minutes: 10
|
|
54
43
|
run: bundle exec rake
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Memcheck
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: ${{matrix.ruby}} on ${{matrix.os}}
|
|
11
|
+
runs-on: ${{matrix.os}}-latest
|
|
12
|
+
continue-on-error: ${{matrix.experimental}}
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
os:
|
|
17
|
+
- ubuntu
|
|
18
|
+
|
|
19
|
+
ruby:
|
|
20
|
+
- "3.2"
|
|
21
|
+
- "3.3"
|
|
22
|
+
- "3.4"
|
|
23
|
+
- "4.0"
|
|
24
|
+
|
|
25
|
+
experimental: [false]
|
|
26
|
+
|
|
27
|
+
include:
|
|
28
|
+
- os: ubuntu
|
|
29
|
+
ruby: head
|
|
30
|
+
experimental: true
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
- uses: ruby/setup-ruby@v1
|
|
35
|
+
with:
|
|
36
|
+
ruby-version: ${{matrix.ruby}}
|
|
37
|
+
bundler-cache: true
|
|
38
|
+
- name: Install Valgrind
|
|
39
|
+
run: |
|
|
40
|
+
sudo apt-get update
|
|
41
|
+
sudo apt-get install -y valgrind
|
|
42
|
+
- name: Run tests
|
|
43
|
+
timeout-minutes: 10
|
|
44
|
+
run: bundle exec rake spec:valgrind
|
data/Rakefile
CHANGED
|
@@ -22,7 +22,7 @@ end
|
|
|
22
22
|
|
|
23
23
|
require 'rake/extensiontask'
|
|
24
24
|
|
|
25
|
-
spec =
|
|
25
|
+
spec = Gem::Specification.load("cool.io.gemspec")
|
|
26
26
|
|
|
27
27
|
def configure_cross_compilation(ext)
|
|
28
28
|
unless RUBY_PLATFORM =~ /mswin|mingw/
|
|
@@ -48,24 +48,11 @@ namespace :build do
|
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
require
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
files << f if File.basename(f) =~ /.*spec.*\.rb$/
|
|
57
|
-
end
|
|
58
|
-
cmdline = "#{RUBY} -I.:lib:ext:spec \
|
|
59
|
-
-e '%w[#{files.join(' ')}].each { |f| require f }'"
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
namespace :spec do
|
|
63
|
-
desc "run specs with valgrind"
|
|
64
|
-
task :valgrind => :compile do
|
|
65
|
-
system "valgrind --num-callers=15 \
|
|
66
|
-
--partial-loads-ok=yes --undef-value-errors=no \
|
|
67
|
-
--tool=memcheck --leak-check=yes --track-fds=yes \
|
|
68
|
-
--show-reachable=yes #{specs_command}"
|
|
51
|
+
if RUBY_PLATFORM.include?('linux')
|
|
52
|
+
require 'ruby_memcheck'
|
|
53
|
+
require 'ruby_memcheck/rspec/rake_task'
|
|
54
|
+
namespace :spec do
|
|
55
|
+
RubyMemcheck::RSpec::RakeTask.new(valgrind: :compile)
|
|
69
56
|
end
|
|
70
57
|
end
|
|
71
58
|
|
data/cool.io.gemspec
CHANGED
data/ext/cool.io/buffer.c
CHANGED
|
@@ -28,17 +28,22 @@
|
|
|
28
28
|
|
|
29
29
|
/* Default number of bytes in each node's buffer. Should be >= MTU */
|
|
30
30
|
#define DEFAULT_NODE_SIZE 16384
|
|
31
|
-
static
|
|
31
|
+
static size_t default_node_size = DEFAULT_NODE_SIZE;
|
|
32
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Byte counts are kept in size_t so the accounting cannot wrap while the
|
|
35
|
+
* buffer itself still holds the data. node_size is capped at MAX_BUFFER_SIZE,
|
|
36
|
+
* but size grows with whatever the buffer is asked to hold.
|
|
37
|
+
*/
|
|
33
38
|
struct buffer {
|
|
34
|
-
|
|
39
|
+
size_t size, node_size;
|
|
35
40
|
struct buffer_node *head, *tail;
|
|
36
41
|
struct buffer_node *pool_head, *pool_tail;
|
|
37
42
|
|
|
38
43
|
};
|
|
39
44
|
|
|
40
45
|
struct buffer_node {
|
|
41
|
-
|
|
46
|
+
size_t start, end;
|
|
42
47
|
struct buffer_node *next;
|
|
43
48
|
unsigned char data[0];
|
|
44
49
|
};
|
|
@@ -47,8 +52,8 @@ static VALUE mCoolio = Qnil;
|
|
|
47
52
|
static VALUE cCoolio_Buffer = Qnil;
|
|
48
53
|
|
|
49
54
|
static VALUE Coolio_Buffer_allocate(VALUE klass);
|
|
50
|
-
static void Coolio_Buffer_mark(
|
|
51
|
-
static void Coolio_Buffer_free(
|
|
55
|
+
static void Coolio_Buffer_mark(void *);
|
|
56
|
+
static void Coolio_Buffer_free(void *);
|
|
52
57
|
|
|
53
58
|
static VALUE Coolio_Buffer_default_node_size(VALUE klass);
|
|
54
59
|
static VALUE Coolio_Buffer_set_default_node_size(VALUE klass, VALUE size);
|
|
@@ -64,17 +69,17 @@ static VALUE Coolio_Buffer_to_str(VALUE self);
|
|
|
64
69
|
static VALUE Coolio_Buffer_read_from(VALUE self, VALUE io);
|
|
65
70
|
static VALUE Coolio_Buffer_write_to(VALUE self, VALUE io);
|
|
66
71
|
|
|
67
|
-
static struct buffer *
|
|
72
|
+
static struct buffer *buffer_init(struct buffer *);
|
|
68
73
|
static void buffer_clear(struct buffer * buf);
|
|
69
74
|
static void buffer_free(struct buffer * buf);
|
|
70
75
|
static void buffer_free_pool(struct buffer * buf);
|
|
71
|
-
static void buffer_prepend(struct buffer * buf, char *str,
|
|
72
|
-
static void buffer_append(struct buffer * buf, char *str,
|
|
73
|
-
static void buffer_read(struct buffer * buf, char *str,
|
|
76
|
+
static void buffer_prepend(struct buffer * buf, char *str, size_t len);
|
|
77
|
+
static void buffer_append(struct buffer * buf, char *str, size_t len);
|
|
78
|
+
static void buffer_read(struct buffer * buf, char *str, size_t len);
|
|
74
79
|
static int buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark);
|
|
75
|
-
static void buffer_copy(struct buffer * buf, char *str,
|
|
76
|
-
static
|
|
77
|
-
static
|
|
80
|
+
static void buffer_copy(struct buffer * buf, char *str, size_t len);
|
|
81
|
+
static ssize_t buffer_read_from(struct buffer * buf, int fd);
|
|
82
|
+
static ssize_t buffer_write_to(struct buffer * buf, int fd);
|
|
78
83
|
|
|
79
84
|
/*
|
|
80
85
|
* High-performance I/O buffer intended for use in non-blocking programs
|
|
@@ -86,8 +91,6 @@ static int buffer_write_to(struct buffer * buf, int fd);
|
|
|
86
91
|
void
|
|
87
92
|
Init_coolio_buffer()
|
|
88
93
|
{
|
|
89
|
-
VALUE cCoolio_IO;
|
|
90
|
-
|
|
91
94
|
mCoolio = rb_define_module("Coolio");
|
|
92
95
|
cCoolio_Buffer = rb_define_class_under(mCoolio, "Buffer", rb_cObject);
|
|
93
96
|
rb_define_alloc_func(cCoolio_Buffer, Coolio_Buffer_allocate);
|
|
@@ -114,42 +117,54 @@ Init_coolio_buffer()
|
|
|
114
117
|
rb_define_const(cCoolio_Buffer, "MAX_SIZE", INT2NUM(MAX_BUFFER_SIZE));
|
|
115
118
|
}
|
|
116
119
|
|
|
120
|
+
static const rb_data_type_t Coolio_Buffer_type = {
|
|
121
|
+
"Coolio::Buffer",
|
|
122
|
+
{
|
|
123
|
+
Coolio_Buffer_mark,
|
|
124
|
+
Coolio_Buffer_free,
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
117
128
|
static VALUE
|
|
118
129
|
Coolio_Buffer_allocate(VALUE klass)
|
|
119
130
|
{
|
|
120
|
-
|
|
131
|
+
struct buffer *buf;
|
|
132
|
+
VALUE buffer = TypedData_Make_Struct(klass, struct buffer, &Coolio_Buffer_type, buf);
|
|
133
|
+
|
|
134
|
+
buffer_init(buf);
|
|
135
|
+
return buffer;
|
|
121
136
|
}
|
|
122
137
|
|
|
123
138
|
static void
|
|
124
|
-
Coolio_Buffer_mark(
|
|
139
|
+
Coolio_Buffer_mark(void *buf)
|
|
125
140
|
{
|
|
126
141
|
/* Naively discard the memory pool whenever Ruby garbage collects */
|
|
127
142
|
buffer_free_pool(buf);
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
static void
|
|
131
|
-
Coolio_Buffer_free(
|
|
146
|
+
Coolio_Buffer_free(void * buf)
|
|
132
147
|
{
|
|
133
148
|
buffer_free(buf);
|
|
134
149
|
}
|
|
135
150
|
|
|
136
151
|
/**
|
|
137
152
|
* call-seq:
|
|
138
|
-
* Coolio::Buffer.default_node_size ->
|
|
153
|
+
* Coolio::Buffer.default_node_size -> 16384
|
|
139
154
|
*
|
|
140
155
|
* Retrieves the current value of the default node size.
|
|
141
156
|
*/
|
|
142
157
|
static VALUE
|
|
143
158
|
Coolio_Buffer_default_node_size(VALUE klass)
|
|
144
159
|
{
|
|
145
|
-
return
|
|
160
|
+
return SIZET2NUM(default_node_size);
|
|
146
161
|
}
|
|
147
162
|
|
|
148
163
|
/*
|
|
149
164
|
* safely converts node sizes from Ruby numerics to C and raising
|
|
150
165
|
* ArgumentError or RangeError on invalid sizes
|
|
151
166
|
*/
|
|
152
|
-
static
|
|
167
|
+
static size_t
|
|
153
168
|
convert_node_size(VALUE size)
|
|
154
169
|
{
|
|
155
170
|
if (
|
|
@@ -158,7 +173,7 @@ convert_node_size(VALUE size)
|
|
|
158
173
|
)
|
|
159
174
|
rb_raise(rb_eArgError, "invalid buffer size");
|
|
160
175
|
|
|
161
|
-
return (
|
|
176
|
+
return NUM2SIZET(size);
|
|
162
177
|
}
|
|
163
178
|
|
|
164
179
|
/**
|
|
@@ -188,7 +203,7 @@ Coolio_Buffer_initialize(int argc, VALUE * argv, VALUE self)
|
|
|
188
203
|
struct buffer *buf;
|
|
189
204
|
|
|
190
205
|
if (rb_scan_args(argc, argv, "01", &node_size_obj) == 1) {
|
|
191
|
-
|
|
206
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
192
207
|
|
|
193
208
|
/*
|
|
194
209
|
* Make sure we're not changing the buffer size after data
|
|
@@ -212,7 +227,7 @@ static VALUE
|
|
|
212
227
|
Coolio_Buffer_clear(VALUE self)
|
|
213
228
|
{
|
|
214
229
|
struct buffer *buf;
|
|
215
|
-
|
|
230
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
216
231
|
|
|
217
232
|
buffer_clear(buf);
|
|
218
233
|
|
|
@@ -229,9 +244,9 @@ static VALUE
|
|
|
229
244
|
Coolio_Buffer_size(VALUE self)
|
|
230
245
|
{
|
|
231
246
|
struct buffer *buf;
|
|
232
|
-
|
|
247
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
233
248
|
|
|
234
|
-
return
|
|
249
|
+
return SIZET2NUM(buf->size);
|
|
235
250
|
}
|
|
236
251
|
|
|
237
252
|
/**
|
|
@@ -244,7 +259,7 @@ static VALUE
|
|
|
244
259
|
Coolio_Buffer_empty(VALUE self)
|
|
245
260
|
{
|
|
246
261
|
struct buffer *buf;
|
|
247
|
-
|
|
262
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
248
263
|
|
|
249
264
|
return buf->size > 0 ? Qfalse : Qtrue;
|
|
250
265
|
}
|
|
@@ -259,7 +274,7 @@ static VALUE
|
|
|
259
274
|
Coolio_Buffer_append(VALUE self, VALUE data)
|
|
260
275
|
{
|
|
261
276
|
struct buffer *buf;
|
|
262
|
-
|
|
277
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
263
278
|
|
|
264
279
|
/* Is this needed? Never seen anyone else do it... */
|
|
265
280
|
data = rb_convert_type(data, T_STRING, "String", "to_str");
|
|
@@ -278,7 +293,7 @@ static VALUE
|
|
|
278
293
|
Coolio_Buffer_prepend(VALUE self, VALUE data)
|
|
279
294
|
{
|
|
280
295
|
struct buffer *buf;
|
|
281
|
-
|
|
296
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
282
297
|
|
|
283
298
|
data = rb_convert_type(data, T_STRING, "String", "to_str");
|
|
284
299
|
buffer_prepend(buf, RSTRING_PTR(data), RSTRING_LEN(data));
|
|
@@ -301,15 +316,18 @@ static VALUE
|
|
|
301
316
|
Coolio_Buffer_read(int argc, VALUE * argv, VALUE self)
|
|
302
317
|
{
|
|
303
318
|
VALUE length_obj, str;
|
|
304
|
-
|
|
319
|
+
size_t length;
|
|
305
320
|
struct buffer *buf;
|
|
306
321
|
|
|
307
|
-
|
|
322
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
308
323
|
|
|
309
324
|
if (rb_scan_args(argc, argv, "01", &length_obj) == 1) {
|
|
310
|
-
|
|
311
|
-
|
|
325
|
+
/* Read signed so a negative argument still raises ArgumentError here
|
|
326
|
+
* rather than RangeError out of the conversion */
|
|
327
|
+
long requested = NUM2LONG(length_obj);
|
|
328
|
+
if(requested < 1)
|
|
312
329
|
rb_raise(rb_eArgError, "length must be greater than zero");
|
|
330
|
+
length = (size_t) requested;
|
|
313
331
|
if(length > buf->size)
|
|
314
332
|
length = buf->size;
|
|
315
333
|
} else
|
|
@@ -318,7 +336,7 @@ Coolio_Buffer_read(int argc, VALUE * argv, VALUE self)
|
|
|
318
336
|
if(buf->size == 0)
|
|
319
337
|
return rb_str_new2("");
|
|
320
338
|
|
|
321
|
-
str = rb_str_new(0, length);
|
|
339
|
+
str = rb_str_new(0, (long) length);
|
|
322
340
|
buffer_read(buf, RSTRING_PTR(str), length);
|
|
323
341
|
|
|
324
342
|
return str;
|
|
@@ -340,7 +358,10 @@ Coolio_Buffer_read_frame(VALUE self, VALUE data, VALUE mark)
|
|
|
340
358
|
char mark_c = (char) NUM2INT(mark);
|
|
341
359
|
struct buffer *buf;
|
|
342
360
|
|
|
343
|
-
|
|
361
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
362
|
+
|
|
363
|
+
StringValue(data);
|
|
364
|
+
rb_str_modify(data);
|
|
344
365
|
|
|
345
366
|
if (buffer_read_frame(buf, data, mark_c)) {
|
|
346
367
|
return Qtrue;
|
|
@@ -361,9 +382,9 @@ Coolio_Buffer_to_str(VALUE self)
|
|
|
361
382
|
VALUE str;
|
|
362
383
|
struct buffer *buf;
|
|
363
384
|
|
|
364
|
-
|
|
385
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
365
386
|
|
|
366
|
-
str = rb_str_new(0, buf->size);
|
|
387
|
+
str = rb_str_new(0, (long) buf->size);
|
|
367
388
|
buffer_copy(buf, RSTRING_PTR(str), buf->size);
|
|
368
389
|
|
|
369
390
|
return str;
|
|
@@ -381,14 +402,14 @@ static VALUE
|
|
|
381
402
|
Coolio_Buffer_read_from(VALUE self, VALUE io)
|
|
382
403
|
{
|
|
383
404
|
struct buffer *buf;
|
|
384
|
-
|
|
405
|
+
ssize_t ret;
|
|
385
406
|
#if defined(HAVE_RB_IO_T) || defined(HAVE_RB_IO_DESCRIPTOR)
|
|
386
407
|
rb_io_t *fptr;
|
|
387
408
|
#else
|
|
388
409
|
OpenFile *fptr;
|
|
389
410
|
#endif
|
|
390
411
|
|
|
391
|
-
|
|
412
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
392
413
|
io = rb_convert_type(io, T_FILE, "IO", "to_io");
|
|
393
414
|
GetOpenFile(io, fptr);
|
|
394
415
|
rb_io_set_nonblock(fptr);
|
|
@@ -398,7 +419,7 @@ Coolio_Buffer_read_from(VALUE self, VALUE io)
|
|
|
398
419
|
#else
|
|
399
420
|
ret = buffer_read_from(buf, FPTR_TO_FD(fptr));
|
|
400
421
|
#endif
|
|
401
|
-
return ret == -1 ? Qnil :
|
|
422
|
+
return ret == -1 ? Qnil : SSIZET2NUM(ret);
|
|
402
423
|
}
|
|
403
424
|
|
|
404
425
|
/**
|
|
@@ -419,15 +440,15 @@ Coolio_Buffer_write_to(VALUE self, VALUE io)
|
|
|
419
440
|
OpenFile *fptr;
|
|
420
441
|
#endif
|
|
421
442
|
|
|
422
|
-
|
|
443
|
+
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
423
444
|
io = rb_convert_type(io, T_FILE, "IO", "to_io");
|
|
424
445
|
GetOpenFile(io, fptr);
|
|
425
446
|
rb_io_set_nonblock(fptr);
|
|
426
447
|
|
|
427
448
|
#ifdef HAVE_RB_IO_DESCRIPTOR
|
|
428
|
-
return
|
|
449
|
+
return SSIZET2NUM(buffer_write_to(buf, rb_io_descriptor(io)));
|
|
429
450
|
#else
|
|
430
|
-
return
|
|
451
|
+
return SSIZET2NUM(buffer_write_to(buf, FPTR_TO_FD(fptr)));
|
|
431
452
|
#endif
|
|
432
453
|
}
|
|
433
454
|
|
|
@@ -438,11 +459,8 @@ Coolio_Buffer_write_to(VALUE self, VALUE io)
|
|
|
438
459
|
|
|
439
460
|
/* Create a new buffer */
|
|
440
461
|
static struct buffer *
|
|
441
|
-
|
|
462
|
+
buffer_init(struct buffer *buf)
|
|
442
463
|
{
|
|
443
|
-
struct buffer *buf;
|
|
444
|
-
|
|
445
|
-
buf = (struct buffer *) xmalloc(sizeof(struct buffer));
|
|
446
464
|
buf->head = buf->tail = buf->pool_head = buf->pool_tail = 0;
|
|
447
465
|
buf->size = 0;
|
|
448
466
|
buf->node_size = default_node_size;
|
|
@@ -472,7 +490,7 @@ buffer_free(struct buffer * buf)
|
|
|
472
490
|
buffer_clear(buf);
|
|
473
491
|
buffer_free_pool(buf);
|
|
474
492
|
|
|
475
|
-
|
|
493
|
+
xfree(buf);
|
|
476
494
|
}
|
|
477
495
|
|
|
478
496
|
/* Free the memory pool */
|
|
@@ -484,7 +502,7 @@ buffer_free_pool(struct buffer * buf)
|
|
|
484
502
|
while (buf->pool_head) {
|
|
485
503
|
tmp = buf->pool_head;
|
|
486
504
|
buf->pool_head = tmp->next;
|
|
487
|
-
|
|
505
|
+
xfree(tmp);
|
|
488
506
|
}
|
|
489
507
|
|
|
490
508
|
buf->pool_tail = 0;
|
|
@@ -528,7 +546,7 @@ buffer_node_free(struct buffer * buf, struct buffer_node * node)
|
|
|
528
546
|
|
|
529
547
|
/* Prepend data to the front of the buffer */
|
|
530
548
|
static void
|
|
531
|
-
buffer_prepend(struct buffer * buf, char *str,
|
|
549
|
+
buffer_prepend(struct buffer * buf, char *str, size_t len)
|
|
532
550
|
{
|
|
533
551
|
struct buffer_node *node, *tmp;
|
|
534
552
|
buf->size += len;
|
|
@@ -569,9 +587,9 @@ buffer_prepend(struct buffer * buf, char *str, unsigned len)
|
|
|
569
587
|
|
|
570
588
|
/* Append data to the front of the buffer */
|
|
571
589
|
static void
|
|
572
|
-
buffer_append(struct buffer * buf, char *str,
|
|
590
|
+
buffer_append(struct buffer * buf, char *str, size_t len)
|
|
573
591
|
{
|
|
574
|
-
|
|
592
|
+
size_t nbytes;
|
|
575
593
|
buf->size += len;
|
|
576
594
|
|
|
577
595
|
/* If it fits in the remaining space in the tail */
|
|
@@ -606,9 +624,9 @@ buffer_append(struct buffer * buf, char *str, unsigned len)
|
|
|
606
624
|
|
|
607
625
|
/* Read data from the buffer (and clear what we've read) */
|
|
608
626
|
static void
|
|
609
|
-
buffer_read(struct buffer * buf, char *str,
|
|
627
|
+
buffer_read(struct buffer * buf, char *str, size_t len)
|
|
610
628
|
{
|
|
611
|
-
|
|
629
|
+
size_t nbytes;
|
|
612
630
|
struct buffer_node *tmp;
|
|
613
631
|
|
|
614
632
|
while (buf->size > 0 && len > 0) {
|
|
@@ -642,7 +660,7 @@ buffer_read(struct buffer * buf, char *str, unsigned len)
|
|
|
642
660
|
static int
|
|
643
661
|
buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark)
|
|
644
662
|
{
|
|
645
|
-
|
|
663
|
+
size_t nbytes = 0;
|
|
646
664
|
struct buffer_node *tmp;
|
|
647
665
|
|
|
648
666
|
while (buf->size > 0) {
|
|
@@ -657,7 +675,7 @@ buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark)
|
|
|
657
675
|
}
|
|
658
676
|
|
|
659
677
|
/* Copy less than everything if we found a frame byte */
|
|
660
|
-
rb_str_cat(str, s, nbytes);
|
|
678
|
+
rb_str_cat(str, s, (long) nbytes);
|
|
661
679
|
|
|
662
680
|
/* Fixup the buffer pointers to indicate the bytes were consumed */
|
|
663
681
|
head->start += nbytes;
|
|
@@ -681,9 +699,9 @@ buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark)
|
|
|
681
699
|
|
|
682
700
|
/* Copy data from the buffer without clearing it */
|
|
683
701
|
static void
|
|
684
|
-
buffer_copy(struct buffer * buf, char *str,
|
|
702
|
+
buffer_copy(struct buffer * buf, char *str, size_t len)
|
|
685
703
|
{
|
|
686
|
-
|
|
704
|
+
size_t nbytes;
|
|
687
705
|
struct buffer_node *node;
|
|
688
706
|
|
|
689
707
|
node = buf->head;
|
|
@@ -702,10 +720,10 @@ buffer_copy(struct buffer * buf, char *str, unsigned len)
|
|
|
702
720
|
}
|
|
703
721
|
|
|
704
722
|
/* Write data from the buffer to a file descriptor */
|
|
705
|
-
static
|
|
723
|
+
static ssize_t
|
|
706
724
|
buffer_write_to(struct buffer * buf, int fd)
|
|
707
725
|
{
|
|
708
|
-
|
|
726
|
+
ssize_t bytes_written, total_bytes_written = 0;
|
|
709
727
|
struct buffer_node *tmp;
|
|
710
728
|
|
|
711
729
|
while (buf->head) {
|
|
@@ -723,7 +741,7 @@ buffer_write_to(struct buffer * buf, int fd)
|
|
|
723
741
|
buf->size -= bytes_written;
|
|
724
742
|
|
|
725
743
|
/* If the write blocked... */
|
|
726
|
-
if (bytes_written < buf->head->end - buf->head->start) {
|
|
744
|
+
if ((size_t) bytes_written < buf->head->end - buf->head->start) {
|
|
727
745
|
buf->head->start += bytes_written;
|
|
728
746
|
return total_bytes_written;
|
|
729
747
|
}
|
|
@@ -741,11 +759,11 @@ buffer_write_to(struct buffer * buf, int fd)
|
|
|
741
759
|
|
|
742
760
|
/* Read data from a file descriptor to a buffer */
|
|
743
761
|
/* Append data to the front of the buffer */
|
|
744
|
-
static
|
|
762
|
+
static ssize_t
|
|
745
763
|
buffer_read_from(struct buffer * buf, int fd)
|
|
746
764
|
{
|
|
747
|
-
|
|
748
|
-
|
|
765
|
+
ssize_t bytes_read, total_bytes_read = 0;
|
|
766
|
+
size_t nbytes;
|
|
749
767
|
|
|
750
768
|
/* Empty list needs initialized */
|
|
751
769
|
if (!buf->head) {
|
|
@@ -775,7 +793,7 @@ buffer_read_from(struct buffer * buf, int fd)
|
|
|
775
793
|
buf->tail->next = buffer_node_new(buf);
|
|
776
794
|
buf->tail = buf->tail->next;
|
|
777
795
|
}
|
|
778
|
-
} while (bytes_read == nbytes);
|
|
796
|
+
} while ((size_t) bytes_read == nbytes);
|
|
779
797
|
|
|
780
798
|
return total_bytes_read;
|
|
781
799
|
}
|
data/ext/cool.io/cool.io.h
CHANGED
|
@@ -55,6 +55,12 @@ struct Coolio_Watcher
|
|
|
55
55
|
int enabled;
|
|
56
56
|
VALUE loop;
|
|
57
57
|
|
|
58
|
+
/* Stable copy of the watched path for ev_stat watchers. libev retains the
|
|
59
|
+
* path pointer passed to ev_stat_init() for the lifetime of the watcher, so
|
|
60
|
+
* it must not point into a Ruby String whose buffer GC.compact may relocate.
|
|
61
|
+
* NULL for watcher types that don't use it. */
|
|
62
|
+
char *stat_path;
|
|
63
|
+
|
|
58
64
|
void (*dispatch_callback)(VALUE self, int revents);
|
|
59
65
|
};
|
|
60
66
|
|
|
@@ -68,4 +74,7 @@ void Init_coolio_timer_watcher();
|
|
|
68
74
|
void Init_coolio_stat_watcher();
|
|
69
75
|
void Init_coolio_utils();
|
|
70
76
|
|
|
77
|
+
struct Coolio_Loop *Coolio_Loop_ptr(VALUE loop);
|
|
78
|
+
struct Coolio_Watcher *Coolio_Watcher_ptr(VALUE watcher);
|
|
79
|
+
|
|
71
80
|
#endif
|
data/ext/cool.io/extconf.rb
CHANGED
data/ext/cool.io/iowatcher.c
CHANGED
|
@@ -82,7 +82,7 @@ static VALUE Coolio_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
82
82
|
else
|
|
83
83
|
rb_raise(rb_eArgError, "invalid event type: '%s' (must be 'r', 'w', or 'rw')", flags_str);
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
watcher_data = Coolio_Watcher_ptr(self);
|
|
86
86
|
io = rb_convert_type(io, T_FILE, "IO", "to_io");
|
|
87
87
|
|
|
88
88
|
watcher_data->dispatch_callback = Coolio_IOWatcher_dispatch_callback;
|