sleepy_penguin 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +3 -0
- data/.manifest +8 -2
- data/ChangeLog +295 -0
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/LATEST +19 -5
- data/LICENSE +2 -2
- data/NEWS +22 -0
- data/README +4 -4
- data/TODO +0 -2
- data/ext/sleepy_penguin/epoll.c +165 -88
- data/ext/sleepy_penguin/eventfd.c +89 -91
- data/ext/sleepy_penguin/extconf.rb +1 -0
- data/ext/sleepy_penguin/init.c +7 -0
- data/ext/sleepy_penguin/inotify.c +229 -91
- data/ext/sleepy_penguin/missing_epoll.h +30 -0
- data/ext/sleepy_penguin/missing_inotify.h +57 -0
- data/ext/sleepy_penguin/signalfd.c +335 -0
- data/ext/sleepy_penguin/sleepy_penguin.h +15 -55
- data/ext/sleepy_penguin/timerfd.c +78 -36
- data/ext/sleepy_penguin/util.c +149 -0
- data/lib/sleepy_penguin.rb +0 -6
- data/lib/sleepy_penguin/signalfd/sig_info.rb +20 -0
- data/lib/sleepy_penguin/sp.rb +4 -0
- data/pkg.mk +5 -4
- data/test/test_epoll.rb +29 -0
- data/test/test_epoll_gc.rb +1 -1
- data/test/test_epoll_optimizations.rb +5 -2
- data/test/test_eventfd.rb +24 -6
- data/test/test_inotify.rb +80 -1
- data/test/test_signalfd.rb +94 -0
- data/test/test_signalfd_siginfo.rb +32 -0
- data/test/test_timerfd.rb +34 -4
- metadata +22 -10
- data/ext/sleepy_penguin/nonblock.h +0 -19
- data/script/isolate_for_tests +0 -30
data/ext/sleepy_penguin/epoll.c
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
#include "sleepy_penguin.h"
|
2
2
|
#include <sys/epoll.h>
|
3
3
|
#include <pthread.h>
|
4
|
+
#include "missing_epoll.h"
|
4
5
|
#ifdef HAVE_RUBY_ST_H
|
5
6
|
# include <ruby/st.h>
|
6
7
|
#else
|
7
8
|
# include <st.h>
|
8
9
|
#endif
|
9
10
|
|
10
|
-
#ifndef EPOLL_CLOEXEC
|
11
|
-
# define EPOLL_CLOEXEC (int)(02000000)
|
12
|
-
#endif
|
13
|
-
|
14
11
|
#define EP_RECREATE (-2)
|
15
12
|
|
16
13
|
static st_table *active;
|
@@ -49,33 +46,6 @@ static struct rb_epoll *ep_get(VALUE self)
|
|
49
46
|
return ep;
|
50
47
|
}
|
51
48
|
|
52
|
-
#ifndef HAVE_EPOLL_CREATE1
|
53
|
-
/*
|
54
|
-
* fake epoll_create1() since some systems don't have it.
|
55
|
-
* Don't worry about thread-safety since current Ruby 1.9 won't
|
56
|
-
* call this without GVL.
|
57
|
-
*/
|
58
|
-
static int my_epoll_create1(int flags)
|
59
|
-
{
|
60
|
-
int fd = epoll_create(1024); /* size ignored since 2.6.8 */
|
61
|
-
|
62
|
-
if (fd < 0 || flags == 0)
|
63
|
-
return fd;
|
64
|
-
|
65
|
-
if ((flags & EPOLL_CLOEXEC) && (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1))
|
66
|
-
goto err;
|
67
|
-
return fd;
|
68
|
-
err:
|
69
|
-
{
|
70
|
-
int saved_errno = errno;
|
71
|
-
close(fd);
|
72
|
-
errno = saved_errno;
|
73
|
-
return -1;
|
74
|
-
}
|
75
|
-
}
|
76
|
-
#define epoll_create1 my_epoll_create1
|
77
|
-
#endif
|
78
|
-
|
79
49
|
static void gcmark(void *ptr)
|
80
50
|
{
|
81
51
|
struct rb_epoll *ep = ptr;
|
@@ -149,31 +119,19 @@ static void ep_check(struct rb_epoll *ep)
|
|
149
119
|
}
|
150
120
|
|
151
121
|
/*
|
152
|
-
*
|
153
|
-
*
|
154
|
-
*
|
155
|
-
*
|
122
|
+
* call-seq:
|
123
|
+
* SleepyPenguin::Epoll.new([flags]) -> Epoll object
|
124
|
+
*
|
125
|
+
* Creates a new Epoll object with an optional +flags+ argument.
|
126
|
+
* +flags+ may currently be +:CLOEXEC+ or +0+ (or +nil+).
|
156
127
|
*/
|
157
128
|
static VALUE init(int argc, VALUE *argv, VALUE self)
|
158
129
|
{
|
159
|
-
int flags;
|
160
130
|
struct rb_epoll *ep = ep_get(self);
|
161
131
|
VALUE fl;
|
162
132
|
|
163
133
|
rb_scan_args(argc, argv, "01", &fl);
|
164
|
-
|
165
|
-
flags = 0;
|
166
|
-
} else {
|
167
|
-
switch (TYPE(fl)) {
|
168
|
-
case T_FIXNUM:
|
169
|
-
case T_BIGNUM:
|
170
|
-
flags = NUM2INT(fl);
|
171
|
-
break;
|
172
|
-
default:
|
173
|
-
rb_raise(rb_eArgError, "flags must be an integer");
|
174
|
-
}
|
175
|
-
}
|
176
|
-
ep->flags = flags;
|
134
|
+
ep->flags = rb_sp_get_flags(self, fl);
|
177
135
|
my_epoll_create(ep);
|
178
136
|
|
179
137
|
return self;
|
@@ -183,11 +141,11 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op)
|
|
183
141
|
{
|
184
142
|
struct epoll_event event;
|
185
143
|
struct rb_epoll *ep = ep_get(self);
|
186
|
-
int fd =
|
144
|
+
int fd = rb_sp_fileno(io);
|
187
145
|
int rv;
|
188
146
|
|
189
147
|
ep_check(ep);
|
190
|
-
event.events =
|
148
|
+
event.events = rb_sp_get_uflags(self, flags);
|
191
149
|
pack_event_data(&event, io);
|
192
150
|
|
193
151
|
rv = epoll_ctl(ep->fd, op, fd, &event);
|
@@ -204,6 +162,7 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op)
|
|
204
162
|
rb_ary_store(ep->marks, fd, io);
|
205
163
|
/* fall-through */
|
206
164
|
case EPOLL_CTL_MOD:
|
165
|
+
flags = UINT2NUM(event.events);
|
207
166
|
rb_ary_store(ep->flag_cache, fd, flags);
|
208
167
|
break;
|
209
168
|
case EPOLL_CTL_DEL:
|
@@ -215,19 +174,30 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op)
|
|
215
174
|
}
|
216
175
|
|
217
176
|
/*
|
218
|
-
*
|
219
|
-
*
|
177
|
+
* call-seq:
|
178
|
+
* ep.set(io, flags) -> 0
|
179
|
+
*
|
180
|
+
* Used to avoid exceptions when your app is too lazy to check
|
181
|
+
* what state a descriptor is in, this sets the epoll descriptor
|
182
|
+
* to watch an +io+ with the given +flags+
|
183
|
+
*
|
184
|
+
* +flags+ may be an array of symbols or an unsigned Integer bit mask:
|
185
|
+
*
|
186
|
+
* - flags = [ :IN, :ET ]
|
187
|
+
* - flags = SleepyPenguin::Epoll::IN | SleepyPenguin::Epoll::ET
|
188
|
+
*
|
189
|
+
* See constants in Epoll for more information.
|
220
190
|
*/
|
221
191
|
static VALUE set(VALUE self, VALUE io, VALUE flags)
|
222
192
|
{
|
223
193
|
struct epoll_event event;
|
224
194
|
struct rb_epoll *ep = ep_get(self);
|
225
|
-
int fd =
|
195
|
+
int fd = rb_sp_fileno(io);
|
226
196
|
int rv;
|
227
197
|
VALUE cur_io = rb_ary_entry(ep->marks, fd);
|
228
198
|
|
229
199
|
ep_check(ep);
|
230
|
-
event.events =
|
200
|
+
event.events = rb_sp_get_uflags(self, flags);
|
231
201
|
pack_event_data(&event, io);
|
232
202
|
|
233
203
|
if (cur_io == io) {
|
@@ -261,30 +231,34 @@ fallback_add:
|
|
261
231
|
}
|
262
232
|
rb_ary_store(ep->marks, fd, io);
|
263
233
|
}
|
234
|
+
flags = UINT2NUM(event.events);
|
264
235
|
rb_ary_store(ep->flag_cache, fd, flags);
|
265
236
|
|
266
237
|
return INT2NUM(rv);
|
267
238
|
}
|
268
239
|
|
269
240
|
/*
|
270
|
-
*
|
271
|
-
*
|
272
|
-
*
|
241
|
+
* call-seq:
|
242
|
+
* epoll.delete(io) -> io or nil
|
243
|
+
*
|
244
|
+
* Stops an +io+ object from being monitored. This is like Epoll#del
|
245
|
+
* but returns +nil+ on ENOENT instead of raising an error. This is
|
246
|
+
* useful for apps that do not care to track the status of an
|
273
247
|
* epoll object itself.
|
274
248
|
*/
|
275
249
|
static VALUE delete(VALUE self, VALUE io)
|
276
250
|
{
|
277
251
|
struct rb_epoll *ep = ep_get(self);
|
278
|
-
int fd =
|
252
|
+
int fd = rb_sp_fileno(io);
|
279
253
|
int rv;
|
280
254
|
VALUE cur_io;
|
281
255
|
|
282
256
|
ep_check(ep);
|
283
|
-
if (
|
257
|
+
if (rb_sp_io_closed(io))
|
284
258
|
goto out;
|
285
259
|
|
286
260
|
cur_io = rb_ary_entry(ep->marks, fd);
|
287
|
-
if (NIL_P(cur_io) ||
|
261
|
+
if (NIL_P(cur_io) || rb_sp_io_closed(cur_io))
|
288
262
|
return Qnil;
|
289
263
|
|
290
264
|
rv = epoll_ctl(ep->fd, EPOLL_CTL_DEL, fd, NULL);
|
@@ -340,7 +314,7 @@ static VALUE nogvl_wait(void *args)
|
|
340
314
|
|
341
315
|
static VALUE real_epwait(struct rb_epoll *ep)
|
342
316
|
{
|
343
|
-
int n = (int)
|
317
|
+
int n = (int)rb_sp_io_region(nogvl_wait, ep);
|
344
318
|
|
345
319
|
return epwait_result(ep, n);
|
346
320
|
}
|
@@ -438,11 +412,14 @@ static VALUE real_epwait(struct rb_epoll *ep)
|
|
438
412
|
#endif /* 1.8 Green thread compatibility code */
|
439
413
|
|
440
414
|
/*
|
441
|
-
*
|
415
|
+
* call-seq:
|
416
|
+
* epoll.wait([maxevents[, timeout]]) { |flags, io| ... }
|
442
417
|
*
|
443
|
-
*
|
444
|
-
*
|
445
|
-
*
|
418
|
+
* Calls epoll_wait(2) and yields Integer +flags+ and IO objects watched
|
419
|
+
* for. +maxevents+ is the maximum number of events to process at once,
|
420
|
+
* lower numbers may prevent starvation when used by dup-ed Epoll objects
|
421
|
+
* in multiple threads. +timeout+ is specified in milliseconds, +nil+
|
422
|
+
* (the default) meaning it will block and wait indefinitely.
|
446
423
|
*/
|
447
424
|
static VALUE epwait(int argc, VALUE *argv, VALUE self)
|
448
425
|
{
|
@@ -464,23 +441,51 @@ static VALUE epwait(int argc, VALUE *argv, VALUE self)
|
|
464
441
|
return real_epwait(ep);
|
465
442
|
}
|
466
443
|
|
467
|
-
/*
|
444
|
+
/*
|
445
|
+
* call-seq:
|
446
|
+
* epoll.add(io, flags) -> 0
|
447
|
+
*
|
448
|
+
* Starts watching a given +io+ object with +flags+ which may be an Integer
|
449
|
+
* bitmask or Array representing arrays to watch for. Consider Epoll#set
|
450
|
+
* instead as it is easier to use.
|
451
|
+
*/
|
468
452
|
static VALUE add(VALUE self, VALUE io, VALUE flags)
|
469
453
|
{
|
470
454
|
return ctl(self, io, flags, EPOLL_CTL_ADD);
|
471
455
|
}
|
472
456
|
|
473
|
-
/*
|
457
|
+
/*
|
458
|
+
* call-seq:
|
459
|
+
* epoll.del(io) -> 0
|
460
|
+
*
|
461
|
+
* Disables an IO object from being watched. Consider Epoll#delete as
|
462
|
+
* it is easier to use.
|
463
|
+
*/
|
474
464
|
static VALUE del(VALUE self, VALUE io)
|
475
465
|
{
|
476
|
-
return ctl(self, io,
|
466
|
+
return ctl(self, io, INT2FIX(0), EPOLL_CTL_DEL);
|
477
467
|
}
|
478
468
|
|
469
|
+
/*
|
470
|
+
* call-seq:
|
471
|
+
* epoll.mod(io, flags) -> 0
|
472
|
+
*
|
473
|
+
* Changes the watch for an existing IO object based on +flags+.
|
474
|
+
* Consider Epoll#set instead as it is easier to use.
|
475
|
+
*/
|
479
476
|
static VALUE mod(VALUE self, VALUE io, VALUE flags)
|
480
477
|
{
|
481
478
|
return ctl(self, io, flags, EPOLL_CTL_MOD);
|
482
479
|
}
|
483
480
|
|
481
|
+
/*
|
482
|
+
* call-seq:
|
483
|
+
* epoll.to_io -> Epoll::IO object
|
484
|
+
*
|
485
|
+
* Used to expose the given Epoll object as an Epoll::IO object for IO.select
|
486
|
+
* or IO#stat. This is unlikely to be useful directly, but is used internally
|
487
|
+
* by IO.select.
|
488
|
+
*/
|
484
489
|
static VALUE to_io(VALUE self)
|
485
490
|
{
|
486
491
|
struct rb_epoll *ep = ep_get(self);
|
@@ -493,6 +498,13 @@ static VALUE to_io(VALUE self)
|
|
493
498
|
return ep->io;
|
494
499
|
}
|
495
500
|
|
501
|
+
/*
|
502
|
+
* call-seq:
|
503
|
+
* epoll.close -> nil
|
504
|
+
*
|
505
|
+
* Closes an existing Epoll object and returns memory back to the kernel.
|
506
|
+
* Raises IOError if object is already closed.
|
507
|
+
*/
|
496
508
|
static VALUE epclose(VALUE self)
|
497
509
|
{
|
498
510
|
struct rb_epoll *ep = ep_get(self);
|
@@ -522,6 +534,12 @@ static VALUE epclose(VALUE self)
|
|
522
534
|
return Qnil;
|
523
535
|
}
|
524
536
|
|
537
|
+
/*
|
538
|
+
* call-seq:
|
539
|
+
* epoll.closed? -> true or false
|
540
|
+
*
|
541
|
+
* Returns whether or not an Epoll object is closed.
|
542
|
+
*/
|
525
543
|
static VALUE epclosed(VALUE self)
|
526
544
|
{
|
527
545
|
struct rb_epoll *ep = ep_get(self);
|
@@ -534,7 +552,7 @@ static int cloexec_dup(struct rb_epoll *ep)
|
|
534
552
|
#ifdef F_DUPFD_CLOEXEC
|
535
553
|
int flags = ep->flags & EPOLL_CLOEXEC ? F_DUPFD_CLOEXEC : F_DUPFD;
|
536
554
|
int fd = fcntl(ep->fd, flags, 0);
|
537
|
-
#else
|
555
|
+
#else /* potentially racy on GVL-free systems: */
|
538
556
|
int fd = dup(ep->fd);
|
539
557
|
if (fd >= 0)
|
540
558
|
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
@@ -542,6 +560,15 @@ static int cloexec_dup(struct rb_epoll *ep)
|
|
542
560
|
return fd;
|
543
561
|
}
|
544
562
|
|
563
|
+
/*
|
564
|
+
* call-seq:
|
565
|
+
* epoll.dup -> another Epoll object
|
566
|
+
*
|
567
|
+
* Duplicates an Epoll object and userspace buffers related to this library.
|
568
|
+
* This allows the same epoll object in the Linux kernel to be safely used
|
569
|
+
* across multiple native threads as long as there is one SleepyPenguin::Epoll
|
570
|
+
* object per-thread.
|
571
|
+
*/
|
545
572
|
static VALUE init_copy(VALUE copy, VALUE orig)
|
546
573
|
{
|
547
574
|
struct rb_epoll *a = ep_get(orig);
|
@@ -572,30 +599,37 @@ static VALUE init_copy(VALUE copy, VALUE orig)
|
|
572
599
|
return copy;
|
573
600
|
}
|
574
601
|
|
602
|
+
/*
|
603
|
+
* call-seq:
|
604
|
+
* epoll.io_for(io) -> object
|
605
|
+
*
|
606
|
+
* Returns the given IO object currently being watched for. Different
|
607
|
+
* IO objects may internally refer to the same process file descriptor.
|
608
|
+
* Mostly used for debugging.
|
609
|
+
*/
|
575
610
|
static VALUE io_for(VALUE self, VALUE obj)
|
576
611
|
{
|
577
612
|
struct rb_epoll *ep = ep_get(self);
|
578
613
|
|
579
|
-
return rb_ary_entry(ep->marks,
|
614
|
+
return rb_ary_entry(ep->marks, rb_sp_fileno(obj));
|
580
615
|
}
|
581
616
|
|
582
617
|
/*
|
583
|
-
*
|
584
|
-
*
|
585
|
-
* epoll.flags_for(io) => Integer
|
618
|
+
* call-seq:
|
619
|
+
* epoll.flags_for(io) -> Integer
|
586
620
|
*
|
587
621
|
* Returns the flags currently watched for in current Epoll object.
|
622
|
+
* Mostly used for debugging.
|
588
623
|
*/
|
589
624
|
static VALUE flags_for(VALUE self, VALUE obj)
|
590
625
|
{
|
591
626
|
struct rb_epoll *ep = ep_get(self);
|
592
627
|
|
593
|
-
return rb_ary_entry(ep->flag_cache,
|
628
|
+
return rb_ary_entry(ep->flag_cache, rb_sp_fileno(obj));
|
594
629
|
}
|
595
630
|
|
596
631
|
/*
|
597
|
-
*
|
598
|
-
*
|
632
|
+
* call-seq:
|
599
633
|
* epoll.include?(io) => true or false
|
600
634
|
*
|
601
635
|
* Returns whether or not a given IO is watched and prevented from being
|
@@ -606,7 +640,7 @@ static VALUE include_p(VALUE self, VALUE obj)
|
|
606
640
|
{
|
607
641
|
struct rb_epoll *ep = ep_get(self);
|
608
642
|
|
609
|
-
return NIL_P(rb_ary_entry(ep->marks,
|
643
|
+
return NIL_P(rb_ary_entry(ep->marks, rb_sp_fileno(obj))) ? Qfalse : Qtrue;
|
610
644
|
}
|
611
645
|
|
612
646
|
/*
|
@@ -641,8 +675,47 @@ void sleepy_penguin_init_epoll(void)
|
|
641
675
|
{
|
642
676
|
VALUE mSleepyPenguin, cEpoll;
|
643
677
|
|
678
|
+
/*
|
679
|
+
* Document-module: SleepyPenguin
|
680
|
+
*
|
681
|
+
* require "sleepy_penguin"
|
682
|
+
* include SleepyPenguin
|
683
|
+
*
|
684
|
+
* The SleepyPenguin namespace includes the Epoll, Inotify, SignalFD,
|
685
|
+
* TimerFD, EventFD classes in its top level and no other constants.
|
686
|
+
*
|
687
|
+
* If you are uncomfortable including SleepyPenguin, you may also
|
688
|
+
* use the "SP" alias if it doesn't conflict with existing code:
|
689
|
+
*
|
690
|
+
* require "sleepy_penguin/sp"
|
691
|
+
*
|
692
|
+
* And then access classes via:
|
693
|
+
*
|
694
|
+
* - SP::Epoll
|
695
|
+
* - SP::EventFD
|
696
|
+
* - SP::Inotify
|
697
|
+
* - SP::SignalFD
|
698
|
+
* - SP::TimerFD
|
699
|
+
*/
|
644
700
|
mSleepyPenguin = rb_define_module("SleepyPenguin");
|
701
|
+
|
702
|
+
/*
|
703
|
+
* Document-class: SleepyPenguin::Epoll
|
704
|
+
*
|
705
|
+
* The Epoll class provides access to epoll(7) functionality in the
|
706
|
+
* Linux 2.6 kernel. It provides fork and GC-safety for Ruby
|
707
|
+
* objects stored within the IO object and may be passed as an
|
708
|
+
* argument to IO.select.
|
709
|
+
*/
|
645
710
|
cEpoll = rb_define_class_under(mSleepyPenguin, "Epoll", rb_cObject);
|
711
|
+
|
712
|
+
/*
|
713
|
+
* Document-class: SleepyPenguin::Epoll::IO
|
714
|
+
*
|
715
|
+
* Epoll::IO is an internal class. Its only purpose is to be
|
716
|
+
* compatible with IO.select and related methods and should not
|
717
|
+
* be used directly, use Epoll instead.
|
718
|
+
*/
|
646
719
|
cEpoll_IO = rb_define_class_under(cEpoll, "IO", rb_cIO);
|
647
720
|
rb_define_method(cEpoll, "initialize", init, -1);
|
648
721
|
rb_define_method(cEpoll, "initialize_copy", init_copy, 1);
|
@@ -660,39 +733,43 @@ void sleepy_penguin_init_epoll(void)
|
|
660
733
|
rb_define_method(cEpoll, "set", set, 2);
|
661
734
|
rb_define_method(cEpoll, "wait", epwait, -1);
|
662
735
|
|
663
|
-
/* specifies
|
736
|
+
/* specifies whether close-on-exec flag is set for Epoll.new */
|
664
737
|
rb_define_const(cEpoll, "CLOEXEC", INT2NUM(EPOLL_CLOEXEC));
|
665
738
|
|
666
739
|
/* watch for read/recv operations */
|
667
|
-
rb_define_const(cEpoll, "IN",
|
740
|
+
rb_define_const(cEpoll, "IN", UINT2NUM(EPOLLIN));
|
668
741
|
|
669
742
|
/* watch for write/send operations */
|
670
|
-
rb_define_const(cEpoll, "OUT",
|
743
|
+
rb_define_const(cEpoll, "OUT", UINT2NUM(EPOLLOUT));
|
671
744
|
|
672
745
|
#ifdef EPOLLRDHUP
|
673
|
-
/*
|
674
|
-
|
746
|
+
/*
|
747
|
+
* Watch a specified io for shutdown(SHUT_WR) on the remote-end.
|
748
|
+
* Available since Linux 2.6.17.
|
749
|
+
*/
|
750
|
+
rb_define_const(cEpoll, "RDHUP", UINT2NUM(EPOLLRDHUP));
|
675
751
|
#endif
|
752
|
+
|
676
753
|
/* watch for urgent read(2) data */
|
677
|
-
rb_define_const(cEpoll, "PRI",
|
754
|
+
rb_define_const(cEpoll, "PRI", UINT2NUM(EPOLLPRI));
|
678
755
|
|
679
756
|
/*
|
680
757
|
* watch for errors, there is no need to specify this,
|
681
758
|
* it is always monitored when an IO is watched
|
682
759
|
*/
|
683
|
-
rb_define_const(cEpoll, "ERR",
|
760
|
+
rb_define_const(cEpoll, "ERR", UINT2NUM(EPOLLERR));
|
684
761
|
|
685
762
|
/*
|
686
763
|
* watch for hangups, there is no need to specify this,
|
687
764
|
* it is always monitored when an IO is watched
|
688
765
|
*/
|
689
|
-
rb_define_const(cEpoll, "HUP",
|
766
|
+
rb_define_const(cEpoll, "HUP", UINT2NUM(EPOLLHUP));
|
690
767
|
|
691
768
|
/* notifications are only Edge Triggered, see epoll(7) */
|
692
|
-
rb_define_const(cEpoll, "ET",
|
769
|
+
rb_define_const(cEpoll, "ET", UINT2NUM((uint32_t)EPOLLET));
|
693
770
|
|
694
771
|
/* unwatch the descriptor once any event has fired */
|
695
|
-
rb_define_const(cEpoll, "ONESHOT",
|
772
|
+
rb_define_const(cEpoll, "ONESHOT", UINT2NUM(EPOLLONESHOT));
|
696
773
|
|
697
774
|
id_for_fd = rb_intern("for_fd");
|
698
775
|
active = st_init_numtable();
|