sleepy_penguin 1.2.0 → 1.3.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.
- data/.gitignore +1 -0
- data/.wrongdoc.yml +2 -2
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +5 -149
- data/README +2 -2
- data/Rakefile +3 -2
- data/ext/sleepy_penguin/epoll.c +138 -16
- data/ext/sleepy_penguin/extconf.rb +1 -0
- data/ext/sleepy_penguin/sleepy_penguin.h +13 -1
- data/lib/sleepy_penguin.rb +2 -2
- data/pkg.mk +166 -0
- data/script/isolate_for_tests +30 -0
- data/sleepy_penguin.gemspec +2 -1
- data/test/test_epoll.rb +31 -1
- data/test/test_epoll_optimizations.rb +127 -0
- metadata +24 -5
data/.gitignore
CHANGED
data/.wrongdoc.yml
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,155 +1,11 @@
|
|
1
|
-
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
1
|
all::
|
3
|
-
|
4
|
-
RAKE = rake
|
5
|
-
RSYNC = rsync
|
6
|
-
|
7
|
-
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
8
|
-
@./GIT-VERSION-GEN
|
9
|
-
-include GIT-VERSION-FILE
|
10
|
-
-include local.mk
|
11
|
-
ifeq ($(DLEXT),) # "so" for Linux
|
12
|
-
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
|
13
|
-
endif
|
14
|
-
ifeq ($(RUBY_VERSION),)
|
15
|
-
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
16
|
-
endif
|
17
|
-
|
18
|
-
install:
|
19
|
-
$(prep_setup_rb)
|
20
|
-
$(RM) -r .install-tmp
|
21
|
-
mkdir .install-tmp
|
22
|
-
$(RUBY) setup.rb all
|
23
|
-
$(RM) $^
|
24
|
-
$(RM) -r .install-tmp
|
25
|
-
$(prep_setup_rb)
|
26
|
-
|
27
|
-
setup_rb_files := .config InstalledFiles
|
28
|
-
prep_setup_rb := @-$(RM) $(setup_rb_files);$(MAKE) -C $(ext) clean
|
29
|
-
|
30
|
-
extdir := ext/sleepy_penguin
|
31
|
-
clean:
|
32
|
-
-$(MAKE) -C $(extdir) clean
|
33
|
-
$(RM) $(setup_rb_files) $(extdir)/Makefile
|
34
|
-
|
35
|
-
pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
|
36
|
-
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
37
|
-
wrongdoc prepare
|
38
|
-
|
39
|
-
.manifest: ChangeLog
|
40
|
-
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
41
|
-
LC_ALL=C sort > $@+
|
42
|
-
cmp $@+ $@ || mv $@+ $@
|
43
|
-
$(RM) $@+
|
44
|
-
|
45
|
-
doc: .document .wrongdoc.yml
|
46
|
-
find lib ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
47
|
-
$(RM) -r doc
|
48
|
-
wrongdoc all
|
49
|
-
install -m644 COPYING doc/COPYING
|
50
|
-
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
51
|
-
|
52
|
-
ifneq ($(VERSION),)
|
2
|
+
RSYNC_DEST := bogomips.org:/srv/bogomips/sleepy_penguin
|
53
3
|
rfproject := rainbows
|
54
4
|
rfpackage := sleepy_penguin
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
release_changes := release_changes-$(VERSION)
|
59
|
-
|
60
|
-
release-notes: $(release_notes)
|
61
|
-
release-changes: $(release_changes)
|
62
|
-
$(release_changes):
|
63
|
-
wrongdoc release_changes > $@+
|
64
|
-
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
65
|
-
$(release_notes):
|
66
|
-
wrongdoc release_notes > $@+
|
67
|
-
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
68
|
-
|
69
|
-
# ensures we're actually on the tagged $(VERSION), only used for release
|
70
|
-
verify:
|
71
|
-
test x"$(shell umask)" = x0022
|
72
|
-
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
73
|
-
git diff-index --quiet HEAD^0
|
74
|
-
test `git rev-parse --verify HEAD^0` = \
|
75
|
-
`git rev-parse --verify refs/tags/v$(VERSION)^{}`
|
76
|
-
|
77
|
-
fix-perms:
|
78
|
-
-git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
79
|
-
-git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
80
|
-
|
81
|
-
gem: $(pkggem)
|
82
|
-
|
83
|
-
install-gem: $(pkggem)
|
84
|
-
gem install $(CURDIR)/$<
|
85
|
-
|
86
|
-
$(pkggem): .manifest fix-perms
|
87
|
-
gem build $(rfpackage).gemspec
|
88
|
-
mkdir -p pkg
|
89
|
-
mv $(@F) $@
|
90
|
-
|
91
|
-
$(pkgtgz): distdir = $(basename $@)
|
92
|
-
$(pkgtgz): HEAD = v$(VERSION)
|
93
|
-
$(pkgtgz): .manifest fix-perms
|
94
|
-
@test -n "$(distdir)"
|
95
|
-
$(RM) -r $(distdir)
|
96
|
-
mkdir -p $(distdir)
|
97
|
-
tar cf - `cat .manifest` | (cd $(distdir) && tar xf -)
|
98
|
-
cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
|
99
|
-
mv $@+ $@
|
100
|
-
|
101
|
-
package: $(pkgtgz) $(pkggem)
|
102
|
-
|
103
|
-
test-release: verify package $(release_notes) $(release_changes)
|
104
|
-
release: verify package $(release_notes) $(release_changes)
|
105
|
-
# make tgz release on RubyForge
|
106
|
-
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
107
|
-
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
108
|
-
# push gem to RubyGems.org
|
109
|
-
gem push $(pkggem)
|
110
|
-
# in case of gem downloads from RubyForge releases page
|
111
|
-
-rubyforge add_file \
|
112
|
-
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
5
|
+
include pkg.mk
|
6
|
+
ifneq ($(VERSION),)
|
7
|
+
release::
|
113
8
|
$(RAKE) raa_update VERSION=$(VERSION)
|
114
9
|
$(RAKE) publish_news VERSION=$(VERSION)
|
115
|
-
else
|
116
|
-
gem install-gem: GIT-VERSION-FILE
|
117
|
-
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
118
10
|
endif
|
119
|
-
|
120
|
-
ext := $(extdir)/sleepy_penguin_ext.$(DLEXT)
|
121
|
-
$(extdir)/Makefile: $(extdir)/extconf.rb
|
122
|
-
cd $(@D) && $(RUBY) extconf.rb
|
123
|
-
|
124
|
-
c_files := $(wildcard $(extdir)/*.[ch] $(extdir)/*/*.h)
|
125
|
-
$(ext): $(c_files) $(extdir)/Makefile
|
126
|
-
$(MAKE) -C $(@D)
|
127
|
-
|
128
|
-
all:: test
|
129
|
-
|
130
|
-
build: $(ext)
|
131
|
-
test_units := $(wildcard test/test_*.rb)
|
132
|
-
test: test-unit
|
133
|
-
test-unit: $(test_units)
|
134
|
-
$(test_units): build
|
135
|
-
$(RUBY) -I lib:$(extdir) $@
|
136
|
-
|
137
|
-
# this requires GNU coreutils variants
|
138
|
-
publish_doc:
|
139
|
-
-git set-file-times
|
140
|
-
$(MAKE) doc
|
141
|
-
find doc/images -type f | \
|
142
|
-
TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
|
143
|
-
$(MAKE) doc_gz
|
144
|
-
chmod 644 $$(find doc -type f)
|
145
|
-
$(RSYNC) -av doc/ bogomips.org:/srv/bogomips/sleepy_penguin/
|
146
|
-
git ls-files | xargs touch
|
147
|
-
|
148
|
-
# Create gzip variants of the same timestamp as the original so nginx
|
149
|
-
# "gzip_static on" can serve the gzipped versions directly.
|
150
|
-
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
151
|
-
doc_gz:
|
152
|
-
for i in $(docs); do \
|
153
|
-
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
154
|
-
|
155
|
-
.PHONY: .FORCE-GIT-VERSION-FILE doc test $(test_units)
|
11
|
+
.PHONY: .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
data/README
CHANGED
@@ -36,13 +36,13 @@ Unpack it, and run "ruby setup.rb"
|
|
36
36
|
|
37
37
|
You can get the latest source via git from the following locations:
|
38
38
|
|
39
|
-
git://
|
39
|
+
git://bogomips.org/sleepy_penguin.git
|
40
40
|
git://repo.or.cz/sleepy_penguin.git (mirror)
|
41
41
|
|
42
42
|
You may browse the code from the web and download the latest snapshot
|
43
43
|
tarballs here:
|
44
44
|
|
45
|
-
* http://
|
45
|
+
* http://bogomips.org/sleepy_penguin.git (cgit)
|
46
46
|
* http://repo.or.cz/w/sleepy_penguin.git (gitweb)
|
47
47
|
|
48
48
|
Inline patches (from "git format-patch") to the mailing list are
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
|
3
|
-
|
2
|
+
require 'wrongdoc'
|
3
|
+
cgit_url = Wrongdoc.config[:cgit_url]
|
4
|
+
git_url = Wrongdoc.config[:git_url]
|
4
5
|
|
5
6
|
desc "post news article to rubyforge"
|
6
7
|
task :publish_news do
|
data/ext/sleepy_penguin/epoll.c
CHANGED
@@ -51,6 +51,7 @@ struct rb_epoll {
|
|
51
51
|
struct epoll_event *events;
|
52
52
|
VALUE io;
|
53
53
|
VALUE marks;
|
54
|
+
VALUE flag_cache;
|
54
55
|
int flags;
|
55
56
|
};
|
56
57
|
|
@@ -95,6 +96,7 @@ static void gcmark(void *ptr)
|
|
95
96
|
|
96
97
|
rb_gc_mark(ep->io);
|
97
98
|
rb_gc_mark(ep->marks);
|
99
|
+
rb_gc_mark(ep->flag_cache);
|
98
100
|
}
|
99
101
|
|
100
102
|
static void gcfree(void *ptr)
|
@@ -124,7 +126,8 @@ static VALUE alloc(VALUE klass)
|
|
124
126
|
self = Data_Make_Struct(klass, struct rb_epoll, gcmark, gcfree, ep);
|
125
127
|
ep->fd = -1;
|
126
128
|
ep->io = Qnil;
|
127
|
-
ep->marks =
|
129
|
+
ep->marks = Qnil;
|
130
|
+
ep->flag_cache = Qnil;
|
128
131
|
ep->capa = step;
|
129
132
|
ep->flags = EPOLL_CLOEXEC;
|
130
133
|
ep->events = xmalloc(sizeof(struct epoll_event) * ep->capa);
|
@@ -145,6 +148,8 @@ static void my_epoll_create(struct rb_epoll *ep)
|
|
145
148
|
rb_sys_fail("epoll_create1");
|
146
149
|
}
|
147
150
|
st_insert(active, (st_data_t)ep->fd, (st_data_t)ep);
|
151
|
+
ep->marks = rb_ary_new();
|
152
|
+
ep->flag_cache = rb_ary_new();
|
148
153
|
}
|
149
154
|
|
150
155
|
static void ep_check(struct rb_epoll *ep)
|
@@ -153,11 +158,15 @@ static void ep_check(struct rb_epoll *ep)
|
|
153
158
|
my_epoll_create(ep);
|
154
159
|
if (ep->fd == -1)
|
155
160
|
rb_raise(rb_eIOError, "closed");
|
161
|
+
assert(TYPE(ep->marks) == T_ARRAY && "marks not initialized");
|
162
|
+
assert(TYPE(ep->flag_cache) == T_ARRAY && "flag_cache not initialized");
|
156
163
|
}
|
157
164
|
|
158
165
|
/*
|
159
166
|
* creates a new Epoll object with an optional +flags+ argument.
|
160
|
-
* +flags+ may currently be
|
167
|
+
* +flags+ may currently be Epoll::CLOEXEC or +0+ (or +nil+)
|
168
|
+
* Epoll::CLOEXEC will be set by default if +nil+ or no
|
169
|
+
* argument is passed.
|
161
170
|
*/
|
162
171
|
static VALUE init(int argc, VALUE *argv, VALUE self)
|
163
172
|
{
|
@@ -204,8 +213,17 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op)
|
|
204
213
|
if (rv == -1)
|
205
214
|
rb_sys_fail("epoll_ctl");
|
206
215
|
}
|
207
|
-
|
216
|
+
switch (op) {
|
217
|
+
case EPOLL_CTL_ADD:
|
208
218
|
rb_ary_store(ep->marks, fd, io);
|
219
|
+
/* fall-through */
|
220
|
+
case EPOLL_CTL_MOD:
|
221
|
+
rb_ary_store(ep->flag_cache, fd, flags);
|
222
|
+
break;
|
223
|
+
case EPOLL_CTL_DEL:
|
224
|
+
rb_ary_store(ep->marks, fd, Qnil);
|
225
|
+
rb_ary_store(ep->flag_cache, fd, Qnil);
|
226
|
+
}
|
209
227
|
|
210
228
|
return INT2NUM(rv);
|
211
229
|
}
|
@@ -220,23 +238,44 @@ static VALUE set(VALUE self, VALUE io, VALUE flags)
|
|
220
238
|
struct rb_epoll *ep = ep_get(self);
|
221
239
|
int fd = my_fileno(io);
|
222
240
|
int rv;
|
241
|
+
VALUE cur_io = rb_ary_entry(ep->marks, fd);
|
223
242
|
|
224
243
|
ep_check(ep);
|
225
244
|
event.events = NUM2UINT(flags);
|
226
245
|
pack_event_data(&event, io);
|
227
246
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
247
|
+
if (cur_io == io) {
|
248
|
+
VALUE cur_flags = rb_ary_entry(ep->flag_cache, fd);
|
249
|
+
uint32_t cur_events;
|
250
|
+
|
251
|
+
assert(!NIL_P(cur_flags) && "cur_flags nil but cur_io is not");
|
252
|
+
cur_events = NUM2UINT(cur_flags);
|
253
|
+
|
254
|
+
if (!(cur_events & EPOLLONESHOT) && cur_events == event.events)
|
255
|
+
return Qnil;
|
234
256
|
|
235
|
-
|
236
|
-
|
257
|
+
fallback_mod:
|
258
|
+
rv = epoll_ctl(ep->fd, EPOLL_CTL_MOD, fd, &event);
|
259
|
+
if (rv == -1) {
|
260
|
+
if (errno != ENOENT)
|
261
|
+
rb_sys_fail("epoll_ctl - mod");
|
262
|
+
errno = 0;
|
263
|
+
rb_warn("epoll flag_cache failed (mod -> add)");
|
264
|
+
goto fallback_add;
|
237
265
|
}
|
238
|
-
|
266
|
+
} else {
|
267
|
+
fallback_add:
|
268
|
+
rv = epoll_ctl(ep->fd, EPOLL_CTL_ADD, fd, &event);
|
269
|
+
if (rv == -1) {
|
270
|
+
if (errno != EEXIST)
|
271
|
+
rb_sys_fail("epoll_ctl - add");
|
272
|
+
errno = 0;
|
273
|
+
rb_warn("epoll flag_cache failed (add -> mod)");
|
274
|
+
goto fallback_mod;
|
275
|
+
}
|
276
|
+
rb_ary_store(ep->marks, fd, io);
|
239
277
|
}
|
278
|
+
rb_ary_store(ep->flag_cache, fd, flags);
|
240
279
|
|
241
280
|
return INT2NUM(rv);
|
242
281
|
}
|
@@ -252,16 +291,27 @@ static VALUE delete(VALUE self, VALUE io)
|
|
252
291
|
struct rb_epoll *ep = ep_get(self);
|
253
292
|
int fd = my_fileno(io);
|
254
293
|
int rv;
|
294
|
+
VALUE cur_io;
|
255
295
|
|
256
296
|
ep_check(ep);
|
297
|
+
cur_io = rb_ary_entry(ep->marks, fd);
|
298
|
+
if (NIL_P(cur_io) || my_io_closed(cur_io))
|
299
|
+
return Qnil;
|
300
|
+
|
257
301
|
rv = epoll_ctl(ep->fd, EPOLL_CTL_DEL, fd, NULL);
|
258
302
|
if (rv == -1) {
|
259
|
-
|
303
|
+
/* beware of IO.for_fd-created descriptors */
|
304
|
+
if (errno == ENOENT || errno == EBADF) {
|
305
|
+
errno = 0;
|
306
|
+
io = Qnil;
|
307
|
+
} else {
|
260
308
|
rb_sys_fail("epoll_ctl - del");
|
261
|
-
|
262
|
-
return Qnil;
|
309
|
+
}
|
263
310
|
}
|
264
|
-
|
311
|
+
rb_ary_store(ep->marks, fd, Qnil);
|
312
|
+
rb_ary_store(ep->flag_cache, fd, Qnil);
|
313
|
+
|
314
|
+
return io;
|
265
315
|
}
|
266
316
|
|
267
317
|
static VALUE epwait_result(struct rb_epoll *ep, int n)
|
@@ -380,6 +430,7 @@ static int epwait_timed(struct rb_epoll *ep)
|
|
380
430
|
if (n > 0 || (n == -1 && errno != EINTR))
|
381
431
|
return n;
|
382
432
|
|
433
|
+
/* XXX use CLOCK_MONOTONIC if people care about 1.8... */
|
383
434
|
gettimeofday(&now, NULL);
|
384
435
|
timersub(&now, &t0, &diff);
|
385
436
|
timersub(&tv, &diff, &tv);
|
@@ -521,7 +572,12 @@ static VALUE init_copy(VALUE copy, VALUE orig)
|
|
521
572
|
NIL_P(b->io) && "Ruby broken?");
|
522
573
|
|
523
574
|
ep_check(a);
|
575
|
+
assert(NIL_P(b->marks) && "mark array not nil");
|
576
|
+
assert(NIL_P(b->flag_cache) && "flag_cache not nil");
|
524
577
|
b->marks = a->marks;
|
578
|
+
b->flag_cache = a->flag_cache;
|
579
|
+
assert(TYPE(b->marks) == T_ARRAY && "mark array not initialized");
|
580
|
+
assert(TYPE(b->flag_cache) == T_ARRAY && "flag_cache not initialized");
|
525
581
|
b->flags = a->flags;
|
526
582
|
b->fd = cloexec_dup(a);
|
527
583
|
if (b->fd == -1) {
|
@@ -537,6 +593,43 @@ static VALUE init_copy(VALUE copy, VALUE orig)
|
|
537
593
|
return copy;
|
538
594
|
}
|
539
595
|
|
596
|
+
static VALUE io_for(VALUE self, VALUE obj)
|
597
|
+
{
|
598
|
+
struct rb_epoll *ep = ep_get(self);
|
599
|
+
|
600
|
+
return rb_ary_entry(ep->marks, my_fileno(obj));
|
601
|
+
}
|
602
|
+
|
603
|
+
/*
|
604
|
+
* :call-seq:
|
605
|
+
*
|
606
|
+
* epoll.flags_for(io) => Integer
|
607
|
+
*
|
608
|
+
* Returns the flags currently watched for in current Epoll object.
|
609
|
+
*/
|
610
|
+
static VALUE flags_for(VALUE self, VALUE obj)
|
611
|
+
{
|
612
|
+
struct rb_epoll *ep = ep_get(self);
|
613
|
+
|
614
|
+
return rb_ary_entry(ep->flag_cache, my_fileno(obj));
|
615
|
+
}
|
616
|
+
|
617
|
+
/*
|
618
|
+
* :call-seq:
|
619
|
+
*
|
620
|
+
* epoll.include?(io) => true or false
|
621
|
+
*
|
622
|
+
* Returns whether or not a given IO is watched and prevented from being
|
623
|
+
* garbage-collected by the current Epoll object. This may include
|
624
|
+
* closed IO objects.
|
625
|
+
*/
|
626
|
+
static VALUE include_p(VALUE self, VALUE obj)
|
627
|
+
{
|
628
|
+
struct rb_epoll *ep = ep_get(self);
|
629
|
+
|
630
|
+
return NIL_P(rb_ary_entry(ep->marks, my_fileno(obj))) ? Qfalse : Qtrue;
|
631
|
+
}
|
632
|
+
|
540
633
|
/*
|
541
634
|
* we close (or lose to GC) epoll descriptors at fork to avoid leakage
|
542
635
|
* and invalid objects being referenced later in the child
|
@@ -582,17 +675,46 @@ void sleepy_penguin_init_epoll(void)
|
|
582
675
|
rb_define_method(cEpoll, "mod", mod, 2);
|
583
676
|
rb_define_method(cEpoll, "del", del, 1);
|
584
677
|
rb_define_method(cEpoll, "delete", delete, 1);
|
678
|
+
rb_define_method(cEpoll, "io_for", io_for, 1);
|
679
|
+
rb_define_method(cEpoll, "flags_for", flags_for, 1);
|
680
|
+
rb_define_method(cEpoll, "include?", include_p, 1);
|
585
681
|
rb_define_method(cEpoll, "set", set, 2);
|
586
682
|
rb_define_method(cEpoll, "wait", epwait, -1);
|
683
|
+
|
684
|
+
/* specifies wheter close-on-exec flag is set for Epoll.new */
|
587
685
|
rb_define_const(cEpoll, "CLOEXEC", INT2NUM(EPOLL_CLOEXEC));
|
686
|
+
|
687
|
+
/* watch for read/recv operations */
|
588
688
|
rb_define_const(cEpoll, "IN", INT2NUM(EPOLLIN));
|
689
|
+
|
690
|
+
/* watch for write/send operations */
|
589
691
|
rb_define_const(cEpoll, "OUT", INT2NUM(EPOLLOUT));
|
692
|
+
|
693
|
+
#ifdef EPOLLRDHUP
|
694
|
+
/* watch a specified IO for shutdown(SHUT_WR) on the remote-end */
|
590
695
|
rb_define_const(cEpoll, "RDHUP", INT2NUM(EPOLLRDHUP));
|
696
|
+
#endif
|
697
|
+
/* watch for urgent read(2) data */
|
591
698
|
rb_define_const(cEpoll, "PRI", INT2NUM(EPOLLPRI));
|
699
|
+
|
700
|
+
/*
|
701
|
+
* watch for errors, there is no need to specify this,
|
702
|
+
* it is always monitored when an IO is watched
|
703
|
+
*/
|
592
704
|
rb_define_const(cEpoll, "ERR", INT2NUM(EPOLLERR));
|
705
|
+
|
706
|
+
/*
|
707
|
+
* watch for hangups, there is no need to specify this,
|
708
|
+
* it is always monitored when an IO is watched
|
709
|
+
*/
|
593
710
|
rb_define_const(cEpoll, "HUP", INT2NUM(EPOLLHUP));
|
711
|
+
|
712
|
+
/* notifications are only Edge Triggered, see epoll(7) */
|
594
713
|
rb_define_const(cEpoll, "ET", INT2NUM(EPOLLET));
|
714
|
+
|
715
|
+
/* unwatch the descriptor once any event has fired */
|
595
716
|
rb_define_const(cEpoll, "ONESHOT", INT2NUM(EPOLLONESHOT));
|
717
|
+
|
596
718
|
id_for_fd = rb_intern("for_fd");
|
597
719
|
active = st_init_numtable();
|
598
720
|
|
@@ -4,6 +4,7 @@ have_header("pthread.h") or abort 'pthread.h not found'
|
|
4
4
|
have_header('sys/eventfd.h')
|
5
5
|
have_header('sys/signalfd.h')
|
6
6
|
have_header('sys/timerfd.h')
|
7
|
+
have_header('ruby/io.h') and have_struct_member('rb_io_t', 'fd', 'ruby/io.h')
|
7
8
|
have_func('rb_memerror')
|
8
9
|
have_func('rb_io_close')
|
9
10
|
have_func('epoll_create1', %w(sys/epoll.h))
|
@@ -26,12 +26,24 @@
|
|
26
26
|
# endif
|
27
27
|
#endif
|
28
28
|
|
29
|
+
#if defined(RFILE) && defined(HAVE_ST_FD)
|
30
|
+
static int my_io_closed(VALUE io)
|
31
|
+
{
|
32
|
+
return RFILE(io)->fptr->fd < 0;
|
33
|
+
}
|
34
|
+
#else
|
35
|
+
static int my_io_closed(VALUE io)
|
36
|
+
{
|
37
|
+
return rb_funcall(io, rb_intern("closed?"), 0) == Qtrue;
|
38
|
+
}
|
39
|
+
#endif
|
40
|
+
|
29
41
|
static int my_fileno(VALUE io)
|
30
42
|
{
|
31
43
|
rb_io_t *fptr;
|
32
44
|
|
33
45
|
switch (TYPE(io)) {
|
34
|
-
case T_FIXNUM: return
|
46
|
+
case T_FIXNUM: return FIX2INT(io);
|
35
47
|
case T_FILE:
|
36
48
|
GetOpenFile(io, fptr);
|
37
49
|
return FPTR_TO_FD(fptr);
|
data/lib/sleepy_penguin.rb
CHANGED
data/pkg.mk
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
RUBY = ruby
|
2
|
+
RAKE = rake
|
3
|
+
RSYNC = rsync
|
4
|
+
|
5
|
+
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
6
|
+
@./GIT-VERSION-GEN
|
7
|
+
-include GIT-VERSION-FILE
|
8
|
+
-include local.mk
|
9
|
+
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
|
10
|
+
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
11
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
12
|
+
lib := lib
|
13
|
+
|
14
|
+
ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
|
15
|
+
isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
|
16
|
+
$(isolate_libs): script/isolate_for_tests
|
17
|
+
@$(RUBY) script/isolate_for_tests
|
18
|
+
-include $(isolate_libs)
|
19
|
+
lib := $(lib):$(ISOLATE_LIBS)
|
20
|
+
endif
|
21
|
+
|
22
|
+
ext := $(firstword $(wildcard ext/*))
|
23
|
+
ifneq ($(ext),)
|
24
|
+
ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
25
|
+
ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
|
26
|
+
ext_src := $(wildcard $(ext)/*.c $(ext_h))
|
27
|
+
ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
|
28
|
+
ext_d := $(ext_pfx)/$(ext)/.d
|
29
|
+
$(ext)/extconf.rb: $(wildcard $(ext)/*.h)
|
30
|
+
@>> $@
|
31
|
+
$(ext_d):
|
32
|
+
@mkdir -p $(@D)
|
33
|
+
@> $@
|
34
|
+
$(ext_pfx)/$(ext)/%: $(ext)/% $(ext_d)
|
35
|
+
install -m 644 $< $@
|
36
|
+
$(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_d) $(ext_h)
|
37
|
+
$(RM) -f $(@D)/*.o
|
38
|
+
cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb
|
39
|
+
ext_sfx := _ext.$(DLEXT)
|
40
|
+
ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
|
41
|
+
$(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
|
42
|
+
@echo $^ == $@
|
43
|
+
$(MAKE) -C $(@D)
|
44
|
+
lib := $(lib):$(ext_pfx)/$(ext)
|
45
|
+
build: $(ext_dl)
|
46
|
+
endif
|
47
|
+
|
48
|
+
pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
|
49
|
+
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
50
|
+
wrongdoc prepare
|
51
|
+
|
52
|
+
manifest:
|
53
|
+
$(RM) .manifest
|
54
|
+
$(MAKE) .manifest
|
55
|
+
|
56
|
+
.manifest: ChangeLog
|
57
|
+
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
58
|
+
LC_ALL=C sort > $@+
|
59
|
+
cmp $@+ $@ || mv $@+ $@
|
60
|
+
$(RM) $@+
|
61
|
+
|
62
|
+
doc: .document .wrongdoc.yml
|
63
|
+
find lib ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
64
|
+
$(RM) -r doc
|
65
|
+
wrongdoc all
|
66
|
+
install -m644 COPYING doc/COPYING
|
67
|
+
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
68
|
+
|
69
|
+
ifneq ($(VERSION),)
|
70
|
+
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
71
|
+
pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
|
72
|
+
release_notes := release_notes-$(VERSION)
|
73
|
+
release_changes := release_changes-$(VERSION)
|
74
|
+
|
75
|
+
release-notes: $(release_notes)
|
76
|
+
release-changes: $(release_changes)
|
77
|
+
$(release_changes):
|
78
|
+
wrongdoc release_changes > $@+
|
79
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
80
|
+
$(release_notes):
|
81
|
+
wrongdoc release_notes > $@+
|
82
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
83
|
+
|
84
|
+
# ensures we're actually on the tagged $(VERSION), only used for release
|
85
|
+
verify:
|
86
|
+
test x"$(shell umask)" = x0022
|
87
|
+
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
88
|
+
git diff-index --quiet HEAD^0
|
89
|
+
test $$(git rev-parse --verify HEAD^0) = \
|
90
|
+
$$(git rev-parse --verify refs/tags/v$(VERSION)^{})
|
91
|
+
|
92
|
+
fix-perms:
|
93
|
+
-git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
94
|
+
-git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
95
|
+
|
96
|
+
gem: $(pkggem)
|
97
|
+
|
98
|
+
install-gem: $(pkggem)
|
99
|
+
gem install $(CURDIR)/$<
|
100
|
+
|
101
|
+
$(pkggem): manifest fix-perms
|
102
|
+
gem build $(rfpackage).gemspec
|
103
|
+
mkdir -p pkg
|
104
|
+
mv $(@F) $@
|
105
|
+
|
106
|
+
$(pkgtgz): distdir = $(basename $@)
|
107
|
+
$(pkgtgz): HEAD = v$(VERSION)
|
108
|
+
$(pkgtgz): manifest fix-perms
|
109
|
+
@test -n "$(distdir)"
|
110
|
+
$(RM) -r $(distdir)
|
111
|
+
mkdir -p $(distdir)
|
112
|
+
tar cf - $$(cat .manifest) | (cd $(distdir) && tar xf -)
|
113
|
+
cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
|
114
|
+
mv $@+ $@
|
115
|
+
|
116
|
+
package: $(pkgtgz) $(pkggem)
|
117
|
+
|
118
|
+
test-release:: verify package $(release_notes) $(release_changes)
|
119
|
+
# make tgz release on RubyForge
|
120
|
+
@echo rubyforge add_release -f \
|
121
|
+
-n $(release_notes) -a $(release_changes) \
|
122
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
123
|
+
@echo gem push $(pkggem)
|
124
|
+
@echo rubyforge add_file \
|
125
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
126
|
+
release:: verify package $(release_notes) $(release_changes)
|
127
|
+
# make tgz release on RubyForge
|
128
|
+
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
129
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
130
|
+
# push gem to RubyGems.org
|
131
|
+
gem push $(pkggem)
|
132
|
+
# in case of gem downloads from RubyForge releases page
|
133
|
+
rubyforge add_file \
|
134
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
135
|
+
else
|
136
|
+
gem install-gem: GIT-VERSION-FILE
|
137
|
+
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
138
|
+
endif
|
139
|
+
|
140
|
+
all:: test
|
141
|
+
test_units := $(wildcard test/test_*.rb)
|
142
|
+
test: test-unit
|
143
|
+
test-unit: $(test_units)
|
144
|
+
$(test_units): build
|
145
|
+
$(RUBY) -I $(lib) $@
|
146
|
+
|
147
|
+
# this requires GNU coreutils variants
|
148
|
+
ifneq ($(RSYNC_DEST),)
|
149
|
+
publish_doc:
|
150
|
+
-git set-file-times
|
151
|
+
$(MAKE) doc
|
152
|
+
find doc/images -type f | \
|
153
|
+
TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
|
154
|
+
$(MAKE) doc_gz
|
155
|
+
$(RSYNC) -av doc/ $(RSYNC_DEST)/
|
156
|
+
git ls-files | xargs touch
|
157
|
+
endif
|
158
|
+
|
159
|
+
# Create gzip variants of the same timestamp as the original so nginx
|
160
|
+
# "gzip_static on" can serve the gzipped versions directly.
|
161
|
+
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
162
|
+
doc_gz:
|
163
|
+
for i in $(docs); do \
|
164
|
+
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
165
|
+
|
166
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# scripts/Makefiles can read and eval the output of this script and
|
3
|
+
# use it as RUBYLIB
|
4
|
+
require 'rubygems'
|
5
|
+
require 'isolate'
|
6
|
+
fp = File.open(__FILE__, "rb")
|
7
|
+
fp.flock(File::LOCK_EX)
|
8
|
+
|
9
|
+
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
10
|
+
opts = {
|
11
|
+
:system => false,
|
12
|
+
# we want "ruby-1.8.7" and not "ruby-1.8", so disable :multiruby
|
13
|
+
:multiruby => false,
|
14
|
+
:path => "tmp/isolate/#{ruby_engine}-#{RUBY_VERSION}",
|
15
|
+
}
|
16
|
+
|
17
|
+
pid = fork do
|
18
|
+
Isolate.now!(opts) do
|
19
|
+
gem 'strace_me', '1.0.0'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
_, status = Process.waitpid2(pid)
|
23
|
+
status.success? or abort status.inspect
|
24
|
+
lib_paths = Dir["#{opts[:path]}/gems/*-*/{lib,ext}"]
|
25
|
+
lib_paths.map! { |x| File.expand_path(x) }
|
26
|
+
dst = "tmp/isolate/#{ruby_engine}-#{RUBY_VERSION}/isolate.mk"
|
27
|
+
File.open("#{dst}.#$$", "w") do |fp|
|
28
|
+
fp.puts "ISOLATE_LIBS=#{lib_paths.join(':')}"
|
29
|
+
end
|
30
|
+
File.rename("#{dst}.#$$", dst)
|
data/sleepy_penguin.gemspec
CHANGED
@@ -7,7 +7,7 @@ name, summary, title = readme_metadata
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = %q{sleepy_penguin}
|
9
9
|
s.version = ENV["VERSION"].dup
|
10
|
-
s.homepage =
|
10
|
+
s.homepage = Wrongdoc.config[:rdoc_url]
|
11
11
|
s.authors = ["#{name} hackers"]
|
12
12
|
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
13
13
|
s.description = readme_description
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.test_files = Dir['test/test_*.rb']
|
22
22
|
s.extensions = %w(ext/sleepy_penguin/extconf.rb)
|
23
23
|
s.add_development_dependency('wrongdoc', '~> 1.3')
|
24
|
+
s.add_development_dependency('strace_me', '~> 1.0')
|
24
25
|
|
25
26
|
# s.license = %w(LGPL) # disabled for compatibility with older RubyGems
|
26
27
|
end
|
data/test/test_epoll.rb
CHANGED
@@ -154,6 +154,8 @@ class TestEpoll < Test::Unit::TestCase
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def test_rdhup
|
157
|
+
defined?(Epoll::RDHUP) or
|
158
|
+
return warn "skipping test, EPOLLRDHUP not available"
|
157
159
|
rd, wr = UNIXSocket.pair
|
158
160
|
@ep.add rd, Epoll::RDHUP
|
159
161
|
tmp = []
|
@@ -318,7 +320,35 @@ class TestEpoll < Test::Unit::TestCase
|
|
318
320
|
assert_nil @ep.delete(@rd)
|
319
321
|
assert_nil @ep.delete(@wr)
|
320
322
|
assert_nothing_raised { @ep.add @rd, Epoll::IN }
|
321
|
-
assert_equal
|
323
|
+
assert_equal @rd, @ep.delete(@rd)
|
322
324
|
assert_nil @ep.delete(@rd)
|
323
325
|
end
|
326
|
+
|
327
|
+
def test_io_for
|
328
|
+
@ep.add @rd, Epoll::IN
|
329
|
+
assert_equal @rd, @ep.io_for(@rd.fileno)
|
330
|
+
assert_equal @rd, @ep.io_for(@rd)
|
331
|
+
@ep.del @rd
|
332
|
+
assert_nil @ep.io_for(@rd.fileno)
|
333
|
+
assert_nil @ep.io_for(@rd)
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_flags_for
|
337
|
+
@ep.add @rd, Epoll::IN
|
338
|
+
assert_equal Epoll::IN, @ep.flags_for(@rd.fileno)
|
339
|
+
assert_equal Epoll::IN, @ep.flags_for(@rd)
|
340
|
+
|
341
|
+
@ep.del @rd
|
342
|
+
assert_nil @ep.flags_for(@rd.fileno)
|
343
|
+
assert_nil @ep.flags_for(@rd)
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_include?
|
347
|
+
assert ! @ep.include?(@rd)
|
348
|
+
@ep.add @rd, Epoll::IN
|
349
|
+
assert @ep.include?(@rd)
|
350
|
+
assert @ep.include?(@rd.fileno)
|
351
|
+
assert ! @ep.include?(@wr)
|
352
|
+
assert ! @ep.include?(@wr.fileno)
|
353
|
+
end
|
324
354
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'strace'
|
3
|
+
$-w = true
|
4
|
+
|
5
|
+
require 'sleepy_penguin'
|
6
|
+
|
7
|
+
class TestEpollOptimizations < Test::Unit::TestCase
|
8
|
+
include SleepyPenguin
|
9
|
+
RBX = defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'rbx')
|
10
|
+
IO_PURGATORY = []
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@rd, @wr = IO.pipe
|
14
|
+
@ep = Epoll.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
[ @ep, @rd, @wr ].each { |io| io.close unless io.closed? }
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_set
|
22
|
+
io, err = Strace.me do
|
23
|
+
@ep.set(@wr, Epoll::OUT)
|
24
|
+
@ep.set(@wr, Epoll::OUT)
|
25
|
+
end
|
26
|
+
assert_nil err
|
27
|
+
lines = io.readlines; io.close
|
28
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
29
|
+
assert_match /EPOLL_CTL_ADD/, lines.grep(/^epoll_ctl/)[0]
|
30
|
+
|
31
|
+
io, err = Strace.me { @ep.set(@wr, Epoll::OUT | Epoll::ONESHOT) }
|
32
|
+
assert_nil err
|
33
|
+
lines = io.readlines; io.close
|
34
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
35
|
+
assert_match /EPOLL_CTL_MOD/, lines.grep(/^epoll_ctl/)[0]
|
36
|
+
|
37
|
+
io, err = Strace.me { @ep.set(@wr, Epoll::OUT) }
|
38
|
+
assert_nil err
|
39
|
+
lines = io.readlines; io.close
|
40
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
41
|
+
assert_match /EPOLL_CTL_MOD/, lines.grep(/^epoll_ctl/)[0]
|
42
|
+
@wr.close
|
43
|
+
@rd.close
|
44
|
+
|
45
|
+
@rd, @wr = IO.pipe
|
46
|
+
io, err = Strace.me { @ep.set(@wr, Epoll::OUT) }
|
47
|
+
assert_nil err
|
48
|
+
lines = io.readlines; io.close
|
49
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
50
|
+
assert_match /EPOLL_CTL_ADD/, lines.grep(/^epoll_ctl/)[0]
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_delete
|
54
|
+
@ep.set(@wr, Epoll::OUT)
|
55
|
+
rv = true
|
56
|
+
io, err = Strace.me { rv = @ep.delete(@wr) }
|
57
|
+
assert_equal @wr, rv
|
58
|
+
assert_nil err
|
59
|
+
lines = io.readlines; io.close
|
60
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
61
|
+
assert_match %r{=\s+0$}, lines.grep(/^epoll_ctl/)[0]
|
62
|
+
|
63
|
+
rv = true
|
64
|
+
io, err = Strace.me { rv = @ep.delete(@wr) }
|
65
|
+
assert_nil rv
|
66
|
+
assert_nil err
|
67
|
+
lines = io.readlines; io.close
|
68
|
+
assert_equal 0, lines.grep(/^epoll_ctl/).size
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_delete_closed
|
72
|
+
a = @wr.fileno
|
73
|
+
@ep.set(@wr, Epoll::OUT)
|
74
|
+
@rd.close
|
75
|
+
@wr.close
|
76
|
+
@rd, @wr = IO.pipe
|
77
|
+
assert_equal a, @wr.fileno
|
78
|
+
rv = true
|
79
|
+
io, err = Strace.me { rv = @ep.delete(@wr) }
|
80
|
+
lines = io.readlines; io.close
|
81
|
+
assert_nil err
|
82
|
+
assert_nil rv
|
83
|
+
assert_equal 0, lines.grep(/^epoll_ctl/).size
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_delete_aliased_a
|
87
|
+
tmp = IO.for_fd @wr.fileno
|
88
|
+
IO_PURGATORY << tmp
|
89
|
+
@ep.set(tmp, Epoll::OUT)
|
90
|
+
rv = nil
|
91
|
+
io, err = Strace.me { rv = @ep.delete(@wr) }
|
92
|
+
lines = io.readlines; io.close
|
93
|
+
assert_equal @wr, rv
|
94
|
+
assert_nil err
|
95
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
96
|
+
assert_match %r{=\s+0$}, lines.grep(/^epoll_ctl/)[0]
|
97
|
+
assert_equal 0, lines.grep(/ENOENT/).size
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_delete_aliased_b
|
101
|
+
tmp = IO.for_fd @wr.fileno
|
102
|
+
IO_PURGATORY << tmp
|
103
|
+
@ep.set(@wr, Epoll::OUT)
|
104
|
+
rv = nil
|
105
|
+
io, err = Strace.me { rv = @ep.delete(tmp) }
|
106
|
+
lines = io.readlines; io.close
|
107
|
+
assert_equal tmp, rv
|
108
|
+
assert_nil err
|
109
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
110
|
+
assert_match %r{=\s+0$}, lines.grep(/^epoll_ctl/)[0]
|
111
|
+
assert_equal 0, lines.grep(/ENOENT/).size
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_delete_aliased_closed
|
115
|
+
tmp = IO.for_fd @wr.fileno
|
116
|
+
IO_PURGATORY << tmp
|
117
|
+
@ep.set(tmp, Epoll::OUT)
|
118
|
+
@wr.close
|
119
|
+
rv = nil
|
120
|
+
io, err = Strace.me { rv = @ep.delete(tmp) }
|
121
|
+
lines = io.readlines; io.close
|
122
|
+
assert_nil rv
|
123
|
+
assert_nil err
|
124
|
+
assert_equal 1, lines.grep(/^epoll_ctl/).size
|
125
|
+
assert_equal 1, lines.grep(/EBADF/).size
|
126
|
+
end
|
127
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sleepy_penguin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- sleepy_penguin hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-21 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -33,6 +33,21 @@ dependencies:
|
|
33
33
|
version: "1.3"
|
34
34
|
type: :development
|
35
35
|
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: strace_me
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 15
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 0
|
48
|
+
version: "1.0"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
36
51
|
description: |-
|
37
52
|
sleepy_penguin provides access to newer, Linux-only system calls to wait
|
38
53
|
on events from traditionally non-I/O sources. Bindings to the eventfd,
|
@@ -78,10 +93,13 @@ files:
|
|
78
93
|
- ext/sleepy_penguin/timerfd.c
|
79
94
|
- ext/sleepy_penguin/value2timespec.h
|
80
95
|
- lib/sleepy_penguin.rb
|
96
|
+
- pkg.mk
|
97
|
+
- script/isolate_for_tests
|
81
98
|
- setup.rb
|
82
99
|
- sleepy_penguin.gemspec
|
83
100
|
- test/test_epoll.rb
|
84
101
|
- test/test_epoll_gc.rb
|
102
|
+
- test/test_epoll_optimizations.rb
|
85
103
|
- test/test_eventfd.rb
|
86
104
|
- test/test_timerfd.rb
|
87
105
|
has_rdoc: true
|
@@ -93,7 +111,7 @@ rdoc_options:
|
|
93
111
|
- -t
|
94
112
|
- sleepy_penguin - Linux I/O events for Ruby
|
95
113
|
- -W
|
96
|
-
- http://
|
114
|
+
- http://bogomips.org/sleepy_penguin.git/tree/%s
|
97
115
|
require_paths:
|
98
116
|
- lib
|
99
117
|
- ext
|
@@ -123,6 +141,7 @@ signing_key:
|
|
123
141
|
specification_version: 3
|
124
142
|
summary: Linux I/O events for Ruby
|
125
143
|
test_files:
|
144
|
+
- test/test_epoll_optimizations.rb
|
126
145
|
- test/test_epoll.rb
|
127
146
|
- test/test_eventfd.rb
|
128
147
|
- test/test_epoll_gc.rb
|