set close-on-exec by default under Ruby 2.0
[sleepy_penguin.git] / ext / sleepy_penguin / util.c
blob2423af68d884d349a59530939b1b8bbdba5a77ef
1 #include "sleepy_penguin.h"
3 static VALUE klass_for(VALUE klass)
5 return (TYPE(klass) == T_CLASS) ? klass : CLASS_OF(klass);
8 int rb_sp_get_flags(VALUE klass, VALUE flags, int default_flags)
10 switch (TYPE(flags)) {
11 case T_NIL: return default_flags;
12 case T_FIXNUM: return FIX2INT(flags);
13 case T_BIGNUM: return NUM2INT(flags);
14 case T_SYMBOL:
15 return NUM2INT(rb_const_get(klass_for(klass), SYM2ID(flags)));
16 case T_ARRAY: {
17 VALUE *ptr = RARRAY_PTR(flags);
18 long len = RARRAY_LEN(flags);
19 int rv = 0;
21 klass = klass_for(klass);
22 while (--len >= 0) {
23 VALUE tmp = *ptr++;
25 Check_Type(tmp, T_SYMBOL);
26 tmp = rb_const_get(klass, SYM2ID(tmp));
27 rv |= NUM2INT(tmp);
29 return rv;
32 rb_raise(rb_eTypeError, "invalid flags");
33 return 0;
36 unsigned rb_sp_get_uflags(VALUE klass, VALUE flags)
38 switch (TYPE(flags)) {
39 case T_NIL: return 0;
40 case T_FIXNUM: return FIX2UINT(flags);
41 case T_BIGNUM: return NUM2UINT(flags);
42 case T_SYMBOL:
43 return NUM2UINT(rb_const_get(klass_for(klass), SYM2ID(flags)));
44 case T_ARRAY: {
45 VALUE *ptr = RARRAY_PTR(flags);
46 long len = RARRAY_LEN(flags);
47 unsigned rv = 0;
49 klass = klass_for(klass);
50 while (--len >= 0) {
51 VALUE tmp = *ptr++;
53 Check_Type(tmp, T_SYMBOL);
54 tmp = rb_const_get(klass, SYM2ID(tmp));
55 rv |= NUM2UINT(tmp);
57 return rv;
60 rb_raise(rb_eTypeError, "invalid flags");
61 return 0;
64 #if ! HAVE_RB_IO_T
65 # define rb_io_t OpenFile
66 #endif
68 #ifdef GetReadFile
69 # define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
70 #else
71 # if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
72 # define FPTR_TO_FD(fptr) fileno(fptr->f)
73 # else
74 # define FPTR_TO_FD(fptr) fptr->fd
75 # endif
76 #endif
78 static int fixint_closed_p(VALUE io)
80 return (fcntl(FIX2INT(io), F_GETFD) == -1 && errno == EBADF);
83 #if defined(RFILE) && defined(HAVE_ST_FD)
84 static int my_rb_io_closed(VALUE io)
86 return RFILE(io)->fptr->fd < 0;
88 #else
89 static int my_rb_io_closed(VALUE io)
91 return rb_funcall(io, rb_intern("closed?"), 0) == Qtrue;
93 #endif
95 int rb_sp_io_closed(VALUE io)
97 switch (TYPE(io)) {
98 case T_FIXNUM:
99 return fixint_closed_p(io);
100 case T_FILE:
101 break;
102 default:
103 io = rb_convert_type(io, T_FILE, "IO", "to_io");
106 return my_rb_io_closed(io);
109 int rb_sp_fileno(VALUE io)
111 rb_io_t *fptr;
113 io = rb_convert_type(io, T_FILE, "IO", "to_io");
114 GetOpenFile(io, fptr);
115 return FPTR_TO_FD(fptr);
118 void rb_sp_set_nonblock(int fd)
120 int flags = fcntl(fd, F_GETFL);
122 if (flags == -1)
123 rb_sys_fail("fcntl(F_GETFL)");
124 if ((flags & O_NONBLOCK) == O_NONBLOCK)
125 return;
127 * Note: while this is Linux-only and we could safely rely on
128 * ioctl(FIONBIO), needing F_SETFL is an uncommon path, and
129 * F_GETFL is lockless. ioctl(FIONBIO) always acquires a spin
130 * lock, so it's more expensive even if we do not need to change
131 * anything.
133 flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
134 if (flags == -1)
135 rb_sys_fail("fcntl(F_SETFL)");
138 int rb_sp_wait(rb_sp_waitfn waiter, VALUE obj, int *fd)
141 * we need to check the fileno before and after waiting, a close()
142 * could've happened at any time (especially when outside of GVL).
144 int rc = waiter(rb_sp_fileno(obj));
145 *fd = rb_sp_fileno(obj);
146 return rc;