sleepy_penguin 1.4.0 → 2.0.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/.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
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef EPOLL_CLOEXEC
|
2
|
+
# define EPOLL_CLOEXEC (int)(02000000)
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#ifndef HAVE_EPOLL_CREATE1
|
6
|
+
/*
|
7
|
+
* fake epoll_create1() since some systems don't have it.
|
8
|
+
* Don't worry about thread-safety since current Ruby 1.9 won't
|
9
|
+
* call this without GVL.
|
10
|
+
*/
|
11
|
+
static int my_epoll_create1(int flags)
|
12
|
+
{
|
13
|
+
int fd = epoll_create(1024); /* size ignored since 2.6.8 */
|
14
|
+
|
15
|
+
if (fd < 0 || flags == 0)
|
16
|
+
return fd;
|
17
|
+
|
18
|
+
if ((flags & EPOLL_CLOEXEC) && (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1))
|
19
|
+
goto err;
|
20
|
+
return fd;
|
21
|
+
err:
|
22
|
+
{
|
23
|
+
int saved_errno = errno;
|
24
|
+
close(fd);
|
25
|
+
errno = saved_errno;
|
26
|
+
return -1;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
# define epoll_create1 my_epoll_create1
|
30
|
+
#endif
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#ifndef IN_CLOEXEC
|
2
|
+
# define IN_CLOEXEC 02000000
|
3
|
+
#endif
|
4
|
+
#ifndef IN_NONBLOCK
|
5
|
+
# define IN_NONBLOCK O_NONBLOCK
|
6
|
+
#endif
|
7
|
+
#ifndef IN_ATTRIB
|
8
|
+
# define IN_ATTRIB 0x00000004
|
9
|
+
#endif
|
10
|
+
#ifndef IN_ONLYDIR
|
11
|
+
# define IN_ONLYDIR 0x01000000
|
12
|
+
#endif
|
13
|
+
#ifndef IN_DONT_FOLLOW
|
14
|
+
# define IN_DONT_FOLLOW 0x02000000
|
15
|
+
#endif
|
16
|
+
#ifndef IN_EXCL_UNLINK
|
17
|
+
# define IN_EXCL_UNLINK 0x04000000
|
18
|
+
#endif
|
19
|
+
#ifndef IN_MASK_ADD
|
20
|
+
# define IN_MASK_ADD 0x20000000
|
21
|
+
#endif
|
22
|
+
#ifndef IN_ONESHOT
|
23
|
+
# define IN_ONESHOT 0x80000000
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifndef HAVE_INOTIFY_INIT1
|
27
|
+
/*
|
28
|
+
* fake inotify_init1() since some systems don't have it
|
29
|
+
* Don't worry about thread-safety since current Ruby 1.9 won't
|
30
|
+
* call this without GVL.
|
31
|
+
*/
|
32
|
+
static int my_inotify_init1(int flags)
|
33
|
+
{
|
34
|
+
int fd = inotify_init();
|
35
|
+
int tmp;
|
36
|
+
|
37
|
+
if (fd < 0)
|
38
|
+
return fd;
|
39
|
+
if ((flags & IN_CLOEXEC) && (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1))
|
40
|
+
goto fcntl_err;
|
41
|
+
if (flags & IN_NONBLOCK) {
|
42
|
+
tmp = fcntl(fd, F_GETFL);
|
43
|
+
if (tmp == -1)
|
44
|
+
goto fcntl_err;
|
45
|
+
if ((fcntl(fd, F_SETFL, tmp | O_NONBLOCK) != 0))
|
46
|
+
goto fcntl_err;
|
47
|
+
}
|
48
|
+
|
49
|
+
return fd;
|
50
|
+
fcntl_err:
|
51
|
+
tmp = errno;
|
52
|
+
close(fd);
|
53
|
+
errno = tmp;
|
54
|
+
rb_sys_fail("fcntl");
|
55
|
+
}
|
56
|
+
# define inotify_init1 my_inotify_init1
|
57
|
+
#endif /* HAVE_INOTIFY_INIT1 */
|
@@ -0,0 +1,335 @@
|
|
1
|
+
#ifdef HAVE_SYS_SIGNALFD_H
|
2
|
+
#include "sleepy_penguin.h"
|
3
|
+
#include <signal.h>
|
4
|
+
#include <sys/signalfd.h>
|
5
|
+
static ID id_for_fd, id_list;
|
6
|
+
static VALUE ssi_members;
|
7
|
+
static VALUE cSigInfo;
|
8
|
+
|
9
|
+
/* converts a Symbol, String, or Fixnum to an integer signal */
|
10
|
+
static int sig2int(VALUE sig)
|
11
|
+
{
|
12
|
+
static VALUE list;
|
13
|
+
const char *ptr;
|
14
|
+
long len;
|
15
|
+
|
16
|
+
if (TYPE(sig) == T_FIXNUM)
|
17
|
+
return FIX2INT(sig);
|
18
|
+
|
19
|
+
sig = rb_obj_as_string(sig);
|
20
|
+
len = RSTRING_LEN(sig);
|
21
|
+
ptr = RSTRING_PTR(sig);
|
22
|
+
|
23
|
+
if (len > 3 && !memcmp("SIG", ptr, 3))
|
24
|
+
sig = rb_str_new(ptr + 3, len - 3);
|
25
|
+
|
26
|
+
if (!list) {
|
27
|
+
VALUE tmp = rb_const_get(rb_cObject, rb_intern("Signal"));
|
28
|
+
|
29
|
+
list = rb_funcall(tmp, rb_intern("list"), 0, 0);
|
30
|
+
rb_global_variable(&list);
|
31
|
+
}
|
32
|
+
|
33
|
+
sig = rb_hash_aref(list, sig);
|
34
|
+
if (NIL_P(sig))
|
35
|
+
rb_raise(rb_eArgError, "invalid signal: %s", ptr);
|
36
|
+
|
37
|
+
return NUM2INT(sig);
|
38
|
+
}
|
39
|
+
|
40
|
+
/* fills sigset_t with an Array of signals */
|
41
|
+
static void value2sigset(sigset_t *mask, VALUE set)
|
42
|
+
{
|
43
|
+
sigemptyset(mask);
|
44
|
+
|
45
|
+
switch (TYPE(set)) {
|
46
|
+
case T_NIL: return;
|
47
|
+
case T_ARRAY: {
|
48
|
+
VALUE *ptr = RARRAY_PTR(set);
|
49
|
+
long len = RARRAY_LEN(set);
|
50
|
+
|
51
|
+
while (--len >= 0)
|
52
|
+
sigaddset(mask, sig2int(*ptr++));
|
53
|
+
}
|
54
|
+
break;
|
55
|
+
default:
|
56
|
+
sigaddset(mask, sig2int(set));
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
static int cur_flags(int fd)
|
61
|
+
{
|
62
|
+
int rv = 0;
|
63
|
+
#ifdef SFD_CLOEXEC
|
64
|
+
{
|
65
|
+
int flags = fcntl(fd, F_GETFD);
|
66
|
+
if (flags == -1) rb_sys_fail("fcntl(F_GETFD)");
|
67
|
+
if (flags & FD_CLOEXEC) rv |= SFD_CLOEXEC;
|
68
|
+
}
|
69
|
+
#endif
|
70
|
+
#ifdef SFD_NONBLOCK
|
71
|
+
{
|
72
|
+
int flags = fcntl(fd, F_GETFL);
|
73
|
+
if (flags == -1) rb_sys_fail("fcntl(F_GETFL)");
|
74
|
+
if (flags & O_NONBLOCK) rv |= SFD_NONBLOCK;
|
75
|
+
}
|
76
|
+
#endif
|
77
|
+
return rv;
|
78
|
+
}
|
79
|
+
|
80
|
+
/*
|
81
|
+
* call-seq:
|
82
|
+
* sfd.update!(signals[, flags]) -> sfd
|
83
|
+
*
|
84
|
+
* Updates the signal mask watched for by the given +sfd+.
|
85
|
+
* Takes the same arguments as SignalFD.new.
|
86
|
+
*/
|
87
|
+
static VALUE update_bang(int argc, VALUE *argv, VALUE self)
|
88
|
+
{
|
89
|
+
VALUE vmask, vflags;
|
90
|
+
sigset_t mask;
|
91
|
+
int flags;
|
92
|
+
int fd = rb_sp_fileno(self);
|
93
|
+
int rc;
|
94
|
+
|
95
|
+
rb_scan_args(argc, argv, "02", &vmask, &vflags);
|
96
|
+
flags = NIL_P(vflags) ? cur_flags(fd) : rb_sp_get_flags(self, vflags);
|
97
|
+
value2sigset(&mask, vmask);
|
98
|
+
|
99
|
+
rc = signalfd(fd, &mask, flags);
|
100
|
+
if (rc == -1)
|
101
|
+
rb_sys_fail("signalfd");
|
102
|
+
return self;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* call-seq:
|
107
|
+
* SignalFD.new(signals[, flags]) -> SignalFD IO object
|
108
|
+
*
|
109
|
+
* Creates a new SignalFD object to watch given +signals+ with +flags+.
|
110
|
+
*
|
111
|
+
* +signals+ is an Array of signal names or a single signal name that
|
112
|
+
* Signal.trap understands:
|
113
|
+
*
|
114
|
+
* signals = [ :USR1, "USR2" ]
|
115
|
+
* signals = :USR1
|
116
|
+
* signals = 15
|
117
|
+
*
|
118
|
+
* Starting with Linux 2.6.27, +flags+ may be a mask that consists of any
|
119
|
+
* of the following:
|
120
|
+
*
|
121
|
+
* - :CLOEXEC - set the close-on-exec flag on the new object
|
122
|
+
* - :NONBLOCK - set the non-blocking I/O flag on the new object
|
123
|
+
*/
|
124
|
+
static VALUE s_new(int argc, VALUE *argv, VALUE klass)
|
125
|
+
{
|
126
|
+
VALUE vmask, vflags;
|
127
|
+
sigset_t mask;
|
128
|
+
int flags;
|
129
|
+
int fd;
|
130
|
+
|
131
|
+
rb_scan_args(argc, argv, "02", &vmask, &vflags);
|
132
|
+
flags = rb_sp_get_flags(klass, vflags);
|
133
|
+
value2sigset(&mask, vmask);
|
134
|
+
|
135
|
+
fd = signalfd(-1, &mask, flags);
|
136
|
+
if (fd == -1) {
|
137
|
+
if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
|
138
|
+
rb_gc();
|
139
|
+
fd = signalfd(-1, &mask, flags);
|
140
|
+
}
|
141
|
+
if (fd == -1)
|
142
|
+
rb_sys_fail("signalfd");
|
143
|
+
}
|
144
|
+
|
145
|
+
return rb_funcall(klass, id_for_fd, 1, INT2NUM(fd));
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE ssi_alloc(VALUE klass)
|
149
|
+
{
|
150
|
+
struct signalfd_siginfo *ssi = ALLOC(struct signalfd_siginfo);
|
151
|
+
|
152
|
+
return Data_Wrap_Struct(klass, NULL, -1, ssi);
|
153
|
+
}
|
154
|
+
|
155
|
+
/* :nodoc: */
|
156
|
+
static VALUE ssi_init(VALUE self)
|
157
|
+
{
|
158
|
+
struct signalfd_siginfo *ssi = DATA_PTR(self);
|
159
|
+
|
160
|
+
memset(ssi, 0, sizeof(struct signalfd_siginfo));
|
161
|
+
return self;
|
162
|
+
}
|
163
|
+
|
164
|
+
static VALUE sfd_read(void *args)
|
165
|
+
{
|
166
|
+
struct signalfd_siginfo *ssi = args;
|
167
|
+
int fd = ssi->ssi_fd;
|
168
|
+
ssize_t r = read(fd, ssi, sizeof(struct signalfd_siginfo));
|
169
|
+
|
170
|
+
return (VALUE)r;
|
171
|
+
}
|
172
|
+
|
173
|
+
/*
|
174
|
+
* call-seq:
|
175
|
+
* sfd.take([nonblock]) -> SignalFD::SigInfo object or +nil+
|
176
|
+
*
|
177
|
+
* Returns the next SigInfo object representing a received signal.
|
178
|
+
* If +nonblock+ is specified and true, this may return +nil+
|
179
|
+
*/
|
180
|
+
static VALUE sfd_take(int argc, VALUE *argv, VALUE self)
|
181
|
+
{
|
182
|
+
VALUE rv = ssi_alloc(cSigInfo);
|
183
|
+
struct signalfd_siginfo *ssi = DATA_PTR(rv);
|
184
|
+
ssize_t r;
|
185
|
+
int fd;
|
186
|
+
VALUE nonblock;
|
187
|
+
|
188
|
+
rb_scan_args(argc, argv, "01", &nonblock);
|
189
|
+
fd = rb_sp_fileno(self);
|
190
|
+
if (RTEST(nonblock))
|
191
|
+
rb_sp_set_nonblock(fd);
|
192
|
+
else
|
193
|
+
blocking_io_prepare(fd);
|
194
|
+
retry:
|
195
|
+
ssi->ssi_fd = fd;
|
196
|
+
r = (ssize_t)rb_sp_io_region(sfd_read, ssi);
|
197
|
+
if (r == -1) {
|
198
|
+
if (errno == EAGAIN && RTEST(nonblock))
|
199
|
+
return Qnil;
|
200
|
+
if (rb_io_wait_readable(fd))
|
201
|
+
goto retry;
|
202
|
+
rb_sys_fail("read(signalfd)");
|
203
|
+
}
|
204
|
+
if (r == 0)
|
205
|
+
rb_eof_error(); /* does this ever happen? */
|
206
|
+
return rv;
|
207
|
+
}
|
208
|
+
|
209
|
+
#define SSI_READER_FUNC(FN, FIELD) \
|
210
|
+
static VALUE ssi_##FIELD(VALUE self) { \
|
211
|
+
struct signalfd_siginfo *ssi = DATA_PTR(self); \
|
212
|
+
return FN(ssi->ssi_##FIELD); \
|
213
|
+
}
|
214
|
+
|
215
|
+
SSI_READER_FUNC(UINT2NUM,signo)
|
216
|
+
SSI_READER_FUNC(INT2NUM,errno)
|
217
|
+
SSI_READER_FUNC(INT2NUM,code)
|
218
|
+
SSI_READER_FUNC(UINT2NUM,pid)
|
219
|
+
SSI_READER_FUNC(UINT2NUM,uid)
|
220
|
+
SSI_READER_FUNC(INT2NUM,fd)
|
221
|
+
SSI_READER_FUNC(UINT2NUM,tid)
|
222
|
+
SSI_READER_FUNC(UINT2NUM,band)
|
223
|
+
SSI_READER_FUNC(UINT2NUM,overrun)
|
224
|
+
SSI_READER_FUNC(UINT2NUM,trapno)
|
225
|
+
SSI_READER_FUNC(INT2NUM,status)
|
226
|
+
SSI_READER_FUNC(INT2NUM,int)
|
227
|
+
SSI_READER_FUNC(ULL2NUM,ptr)
|
228
|
+
SSI_READER_FUNC(ULL2NUM,utime)
|
229
|
+
SSI_READER_FUNC(ULL2NUM,stime)
|
230
|
+
SSI_READER_FUNC(ULL2NUM,addr)
|
231
|
+
|
232
|
+
void sleepy_penguin_init_signalfd(void)
|
233
|
+
{
|
234
|
+
VALUE mSleepyPenguin, cSignalFD;
|
235
|
+
|
236
|
+
mSleepyPenguin = rb_define_module("SleepyPenguin");
|
237
|
+
|
238
|
+
/*
|
239
|
+
* Document-class: SleepyPenguin::SignalFD
|
240
|
+
*
|
241
|
+
* A SignalFD is an IO object for accepting signals. It provides
|
242
|
+
* an alternative to Signal.trap that may be monitored using
|
243
|
+
* IO.select or Epoll.
|
244
|
+
*
|
245
|
+
* SignalFD appears interact unpredictably with YARV (Ruby 1.9) signal
|
246
|
+
* handling and has been unreliable in our testing. Since Ruby has a
|
247
|
+
* decent signal handling interface anyways, this class is less useful
|
248
|
+
* than signalfd() in a C-only environment.
|
249
|
+
*
|
250
|
+
* It is not supported at all under (Matz) Ruby 1.8.
|
251
|
+
*/
|
252
|
+
cSignalFD = rb_define_class_under(mSleepyPenguin, "SignalFD", rb_cIO);
|
253
|
+
|
254
|
+
/*
|
255
|
+
* Document-class: SleepyPenguin::SignalFD::SigInfo
|
256
|
+
*
|
257
|
+
* This class is returned by SignalFD#take. It consists of the
|
258
|
+
* following read-only members:
|
259
|
+
*
|
260
|
+
* - signo - signal number
|
261
|
+
* - errno - error number
|
262
|
+
* - code - signal code
|
263
|
+
* - pid - PID of sender
|
264
|
+
* - uid - real UID of sender
|
265
|
+
* - fd - file descriptor (SIGIO)
|
266
|
+
* - tid - kernel timer ID (POSIX timers)
|
267
|
+
* - band - band event (SIGIO)
|
268
|
+
* - overrun - POSIX timer overrun count
|
269
|
+
* - trapno - trap number that caused hardware-generated signal
|
270
|
+
* - exit status or signal (SIGCHLD)
|
271
|
+
* - int - integer sent by sigqueue(2)
|
272
|
+
* - ptr - Pointer sent by sigqueue(2)
|
273
|
+
* - utime - User CPU time consumed (SIGCHLD)
|
274
|
+
* - stime - System CPU time consumed (SIGCHLD)
|
275
|
+
* - addr - address that generated a hardware-generated signal
|
276
|
+
*/
|
277
|
+
cSigInfo = rb_define_class_under(cSignalFD, "SigInfo", rb_cObject);
|
278
|
+
rb_define_alloc_func(cSigInfo, ssi_alloc);
|
279
|
+
rb_define_private_method(cSigInfo, "initialize", ssi_init, 0);
|
280
|
+
|
281
|
+
/* TODO: si_code values */
|
282
|
+
|
283
|
+
rb_define_singleton_method(cSignalFD, "new", s_new, -1);
|
284
|
+
#ifdef SFD_NONBLOCK
|
285
|
+
NODOC_CONST(cSignalFD, "NONBLOCK", INT2NUM(SFD_NONBLOCK));
|
286
|
+
#endif
|
287
|
+
#ifdef SFD_CLOEXEC
|
288
|
+
NODOC_CONST(cSignalFD, "CLOEXEC", INT2NUM(SFD_CLOEXEC));
|
289
|
+
#endif
|
290
|
+
|
291
|
+
rb_define_method(cSignalFD, "take", sfd_take, -1);
|
292
|
+
rb_define_method(cSignalFD, "update!", update_bang, -1);
|
293
|
+
id_for_fd = rb_intern("for_fd");
|
294
|
+
ssi_members = rb_ary_new();
|
295
|
+
|
296
|
+
NODOC_CONST(cSigInfo, "MEMBERS", ssi_members);
|
297
|
+
|
298
|
+
/*
|
299
|
+
* the minimum signal number for real-time signals,
|
300
|
+
* 34 on NPTL-based systems
|
301
|
+
*/
|
302
|
+
rb_define_const(cSignalFD, "RTMIN", INT2NUM(SIGRTMIN));
|
303
|
+
|
304
|
+
/*
|
305
|
+
* the maximum signal number for real-time signals,
|
306
|
+
* 64 on NPTL-based systems
|
307
|
+
*/
|
308
|
+
rb_define_const(cSignalFD, "RTMAX", INT2NUM(SIGRTMAX));
|
309
|
+
|
310
|
+
#define SSI_READER(FIELD) do { \
|
311
|
+
rb_define_method(cSigInfo, #FIELD, ssi_##FIELD, 0); \
|
312
|
+
rb_ary_push(ssi_members, ID2SYM(rb_intern(#FIELD))); \
|
313
|
+
} while (0)
|
314
|
+
|
315
|
+
SSI_READER(signo);
|
316
|
+
SSI_READER(errno);
|
317
|
+
SSI_READER(code);
|
318
|
+
SSI_READER(pid);
|
319
|
+
SSI_READER(uid);
|
320
|
+
SSI_READER(fd);
|
321
|
+
SSI_READER(tid);
|
322
|
+
SSI_READER(band);
|
323
|
+
SSI_READER(overrun);
|
324
|
+
SSI_READER(trapno);
|
325
|
+
SSI_READER(status);
|
326
|
+
SSI_READER(int);
|
327
|
+
SSI_READER(ptr);
|
328
|
+
SSI_READER(utime);
|
329
|
+
SSI_READER(stime);
|
330
|
+
SSI_READER(addr);
|
331
|
+
rb_obj_freeze(ssi_members);
|
332
|
+
|
333
|
+
rb_require("sleepy_penguin/signalfd/sig_info");
|
334
|
+
}
|
335
|
+
#endif /* HAVE_SYS_SIGNALFD_H */
|
@@ -12,64 +12,24 @@
|
|
12
12
|
#include <assert.h>
|
13
13
|
#include <unistd.h>
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
|
23
|
-
# define FPTR_TO_FD(fptr) fileno(fptr->f)
|
24
|
-
# else
|
25
|
-
# define FPTR_TO_FD(fptr) fptr->fd
|
26
|
-
# endif
|
27
|
-
#endif
|
28
|
-
|
29
|
-
static int fixint_closed_p(VALUE io)
|
15
|
+
unsigned rb_sp_get_uflags(VALUE klass, VALUE flags);
|
16
|
+
int rb_sp_get_flags(VALUE klass, VALUE flags);
|
17
|
+
int rb_sp_io_closed(VALUE io);
|
18
|
+
int rb_sp_fileno(VALUE io);
|
19
|
+
void rb_sp_set_nonblock(int fd);
|
20
|
+
|
21
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
22
|
+
static inline VALUE rb_sp_io_region(rb_blocking_function_t *func, void *data)
|
30
23
|
{
|
31
|
-
return (
|
32
|
-
}
|
33
|
-
|
34
|
-
#if defined(RFILE) && defined(HAVE_ST_FD)
|
35
|
-
static int my_rb_io_closed(VALUE io)
|
36
|
-
{
|
37
|
-
return RFILE(io)->fptr->fd < 0;
|
24
|
+
return rb_thread_blocking_region(func, data, RUBY_UBF_IO, 0);
|
38
25
|
}
|
26
|
+
# define blocking_io_prepare(fd) ((void)(fd))
|
39
27
|
#else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
28
|
+
typedef VALUE rb_blocking_function_t(void *);
|
29
|
+
VALUE rb_sp_io_region(rb_blocking_function_t *func, void *data);
|
30
|
+
# define blocking_io_prepare(fd) rb_sp_set_nonblock((fd))
|
44
31
|
#endif
|
45
32
|
|
46
|
-
|
47
|
-
|
48
|
-
switch (TYPE(io)) {
|
49
|
-
case T_FIXNUM:
|
50
|
-
return fixint_closed_p(io);
|
51
|
-
case T_FILE:
|
52
|
-
break;
|
53
|
-
default:
|
54
|
-
io = rb_convert_type(io, T_FILE, "IO", "to_io");
|
55
|
-
}
|
56
|
-
|
57
|
-
return my_rb_io_closed(io);
|
58
|
-
}
|
59
|
-
|
60
|
-
static int my_fileno(VALUE io)
|
61
|
-
{
|
62
|
-
rb_io_t *fptr;
|
63
|
-
|
64
|
-
switch (TYPE(io)) {
|
65
|
-
case T_FIXNUM: return FIX2INT(io);
|
66
|
-
case T_FILE:
|
67
|
-
GetOpenFile(io, fptr);
|
68
|
-
return FPTR_TO_FD(fptr);
|
69
|
-
}
|
70
|
-
io = rb_convert_type(io, T_FILE, "IO", "to_io");
|
71
|
-
GetOpenFile(io, fptr);
|
72
|
-
return FPTR_TO_FD(fptr);
|
73
|
-
}
|
74
|
-
|
33
|
+
#define NODOC_CONST(klass,name,value) \
|
34
|
+
rb_define_const((klass),(name),(value))
|
75
35
|
#endif /* SLEEPY_PENGUIN_H */
|