accept.c: reinstate errno after calling my_fileno()
[kgio.git] / ext / kgio / accept.c
blob1a125ca6c75761346949685402be8dd48e0a25f8
1 #include "kgio.h"
2 #include "missing_accept4.h"
3 #include "sock_for_fd.h"
4 #include "my_fileno.h"
5 #include "nonblock.h"
7 static VALUE localhost;
8 static VALUE cClientSocket;
9 static VALUE cKgio_Socket;
10 static VALUE mSocketMethods;
11 static VALUE iv_kgio_addr;
13 #if defined(__linux__)
14 static int accept4_flags = SOCK_CLOEXEC;
15 #else /* ! linux */
16 static int accept4_flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
17 #endif /* ! linux */
19 struct accept_args {
20 int fd;
21 int flags;
22 struct sockaddr *addr;
23 socklen_t *addrlen;
24 VALUE accept_io;
25 VALUE accepted_class;
29 * Sets the default class for newly accepted sockets. This is
30 * legacy behavior, kgio_accept and kgio_tryaccept now take optional
31 * class arguments to override this value.
33 static VALUE set_accepted(VALUE klass, VALUE aclass)
35 VALUE tmp;
37 if (NIL_P(aclass))
38 aclass = cKgio_Socket;
40 tmp = rb_funcall(aclass, rb_intern("included_modules"), 0, 0);
41 tmp = rb_funcall(tmp, rb_intern("include?"), 1, mSocketMethods);
43 if (tmp != Qtrue)
44 rb_raise(rb_eTypeError,
45 "class must include Kgio::SocketMethods");
47 cClientSocket = aclass;
49 return aclass;
53 * Returns the default class for newly accepted sockets when kgio_accept
54 * or kgio_tryaccept are not passed arguments
56 static VALUE get_accepted(VALUE klass)
58 return cClientSocket;
62 * accept() wrapper that'll fall back on accept() if we were built on
63 * a system with accept4() but run on a system without accept4()
65 static VALUE xaccept(void *ptr)
67 struct accept_args *a = ptr;
68 int rv;
70 rv = accept_fn(a->fd, a->addr, a->addrlen, a->flags);
71 if (rv == -1 && errno == ENOSYS && accept_fn != my_accept4) {
72 accept_fn = my_accept4;
73 rv = accept_fn(a->fd, a->addr, a->addrlen, a->flags);
76 return (VALUE)rv;
79 #ifdef HAVE_RB_THREAD_BLOCKING_REGION
80 # include <time.h>
81 # include "blocking_io_region.h"
83 * Try to use a (real) blocking accept() since that can prevent
84 * thundering herds under Linux:
85 * http://www.citi.umich.edu/projects/linux-scalability/reports/accept.html
87 * So we periodically disable non-blocking, but not too frequently
88 * because other processes may set non-blocking (especially during
89 * a process upgrade) with Rainbows! concurrency model changes.
91 static int thread_accept(struct accept_args *a, int force_nonblock)
93 if (force_nonblock)
94 set_nonblocking(a->fd);
95 return (int)rb_thread_io_blocking_region(xaccept, a, a->fd);
98 static void set_blocking_or_block(int fd)
100 static time_t last_set_blocking;
101 time_t now = time(NULL);
103 if (last_set_blocking == 0) {
104 last_set_blocking = now;
105 (void)rb_io_wait_readable(fd);
106 } else if ((now - last_set_blocking) <= 5) {
107 (void)rb_io_wait_readable(fd);
108 } else {
109 int flags = fcntl(fd, F_GETFL);
110 if (flags == -1)
111 rb_sys_fail("fcntl(F_GETFL)");
112 if (flags & O_NONBLOCK) {
113 flags = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
114 if (flags == -1)
115 rb_sys_fail("fcntl(F_SETFL)");
117 last_set_blocking = now;
120 #else /* ! HAVE_RB_THREAD_BLOCKING_REGION */
121 # include <rubysig.h>
122 static int thread_accept(struct accept_args *a, int force_nonblock)
124 int rv;
126 /* always use non-blocking accept() under 1.8 for green threads */
127 set_nonblocking(a->fd);
128 TRAP_BEG;
129 rv = (int)xaccept(a);
130 TRAP_END;
131 return rv;
133 #define set_blocking_or_block(fd) (void)rb_io_wait_readable(fd)
134 #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
136 static void
137 prepare_accept(struct accept_args *a, VALUE self, int argc, const VALUE *argv)
139 a->fd = my_fileno(self);
140 a->accept_io = self;
142 switch (argc) {
143 case 2:
144 a->flags = NUM2INT(argv[1]);
145 a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
146 return;
147 case 0: /* default, legacy behavior */
148 a->flags = accept4_flags;
149 a->accepted_class = cClientSocket;
150 return;
151 case 1:
152 a->flags = accept4_flags;
153 a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
154 return;
157 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
160 static VALUE in_addr_set(VALUE io, struct sockaddr_storage *addr, socklen_t len)
162 VALUE host;
163 int host_len, rc;
164 char *host_ptr;
166 switch (addr->ss_family) {
167 case AF_INET:
168 host_len = (long)INET_ADDRSTRLEN;
169 break;
170 case AF_INET6:
171 host_len = (long)INET6_ADDRSTRLEN;
172 break;
173 default:
174 rb_raise(rb_eRuntimeError, "unsupported address family");
176 host = rb_str_new(NULL, host_len);
177 host_ptr = RSTRING_PTR(host);
178 rc = getnameinfo((struct sockaddr *)addr, len,
179 host_ptr, host_len, NULL, 0, NI_NUMERICHOST);
180 if (rc != 0)
181 rb_raise(rb_eRuntimeError, "getnameinfo: %s", gai_strerror(rc));
182 rb_str_set_len(host, strlen(host_ptr));
183 return rb_ivar_set(io, iv_kgio_addr, host);
186 #if defined(__linux__)
187 # define post_accept kgio_autopush_accept
188 #else
189 # define post_accept(a,b) for(;0;)
190 #endif
192 static VALUE
193 my_accept(struct accept_args *a, int force_nonblock)
195 int client_fd;
196 VALUE client_io;
197 int retried = 0;
199 retry:
200 client_fd = thread_accept(a, force_nonblock);
201 if (client_fd == -1) {
202 switch (errno) {
203 case EAGAIN:
204 if (force_nonblock)
205 return Qnil;
206 a->fd = my_fileno(a->accept_io);
207 errno = EAGAIN;
208 set_blocking_or_block(a->fd);
209 #ifdef ECONNABORTED
210 case ECONNABORTED:
211 #endif /* ECONNABORTED */
212 #ifdef EPROTO
213 case EPROTO:
214 #endif /* EPROTO */
215 case EINTR:
216 a->fd = my_fileno(a->accept_io);
217 goto retry;
218 case ENOMEM:
219 case EMFILE:
220 case ENFILE:
221 #ifdef ENOBUFS
222 case ENOBUFS:
223 #endif /* ENOBUFS */
224 if (!retried) {
225 retried = 1;
226 errno = 0;
227 rb_gc();
228 goto retry;
230 default:
231 rb_sys_fail("accept");
234 client_io = sock_for_fd(a->accepted_class, client_fd);
235 post_accept(a->accept_io, client_io);
237 if (a->addr)
238 in_addr_set(client_io,
239 (struct sockaddr_storage *)a->addr, *a->addrlen);
240 else
241 rb_ivar_set(client_io, iv_kgio_addr, localhost);
242 return client_io;
246 * call-seq:
248 * io.kgio_addr! => refreshes the given sock address
250 static VALUE addr_bang(VALUE io)
252 int fd = my_fileno(io);
253 struct sockaddr_storage addr;
254 socklen_t len = sizeof(struct sockaddr_storage);
256 if (getpeername(fd, (struct sockaddr *)&addr, &len) != 0)
257 rb_sys_fail("getpeername");
259 if (addr.ss_family == AF_UNIX)
260 return rb_ivar_set(io, iv_kgio_addr, localhost);
262 return in_addr_set(io, &addr, len);
266 * call-seq:
268 * server = Kgio::TCPServer.new('0.0.0.0', 80)
269 * server.kgio_tryaccept -> Kgio::Socket or nil
270 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
271 * server.kgio_tryaccept(nil, flags) -> Kgio::Socket or nil
273 * Initiates a non-blocking accept and returns a generic Kgio::Socket
274 * object with the kgio_addr attribute set to the IP address of the
275 * connected client on success.
277 * Returns nil on EAGAIN, and raises on other errors.
279 * An optional +klass+ argument may be specified to override the
280 * Kgio::Socket-class on a successful return value.
282 * An optional +flags+ argument may also be specifed to override the
283 * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+
284 * is a bitmask that may contain any combination of:
286 * - Fcntl::FD_CLOEXEC - close-on-exec flag
287 * - IO::NONBLOCK - non-blocking flag
289 static VALUE tcp_tryaccept(int argc, VALUE *argv, VALUE self)
291 struct sockaddr_storage addr;
292 socklen_t addrlen = sizeof(struct sockaddr_storage);
293 struct accept_args a;
295 a.addr = (struct sockaddr *)&addr;
296 a.addrlen = &addrlen;
297 prepare_accept(&a, self, argc, argv);
298 return my_accept(&a, 1);
302 * call-seq:
304 * server = Kgio::TCPServer.new('0.0.0.0', 80)
305 * server.kgio_accept -> Kgio::Socket or nil
306 * server.kgio_tryaccept -> Kgio::Socket or nil
307 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
309 * Initiates a blocking accept and returns a generic Kgio::Socket
310 * object with the kgio_addr attribute set to the IP address of
311 * the client on success.
313 * On Ruby implementations using native threads, this can use a blocking
314 * accept(2) (or accept4(2)) system call to avoid thundering herds.
316 * An optional +klass+ argument may be specified to override the
317 * Kgio::Socket-class on a successful return value.
319 * An optional +flags+ argument may also be specifed to override the
320 * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+
321 * is a bitmask that may contain any combination of:
323 * - Fcntl::FD_CLOEXEC - close-on-exec flag
324 * - IO::NONBLOCK - non-blocking flag
326 static VALUE tcp_accept(int argc, VALUE *argv, VALUE self)
328 struct sockaddr_storage addr;
329 socklen_t addrlen = sizeof(struct sockaddr_storage);
330 struct accept_args a;
332 a.addr = (struct sockaddr *)&addr;
333 a.addrlen = &addrlen;
334 prepare_accept(&a, self, argc, argv);
335 return my_accept(&a, 0);
339 * call-seq:
341 * server = Kgio::UNIXServer.new("/path/to/unix/socket")
342 * server.kgio_tryaccept -> Kgio::Socket or nil
343 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
344 * server.kgio_tryaccept(nil, flags) -> Kgio::Socket or nil
346 * Initiates a non-blocking accept and returns a generic Kgio::Socket
347 * object with the kgio_addr attribute set (to the value of
348 * Kgio::LOCALHOST) on success.
350 * An optional +klass+ argument may be specified to override the
351 * Kgio::Socket-class on a successful return value.
353 * An optional +flags+ argument may also be specifed to override the
354 * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+
355 * is a bitmask that may contain any combination of:
357 * - Fcntl::FD_CLOEXEC - close-on-exec flag
358 * - IO::NONBLOCK - non-blocking flag
360 static VALUE unix_tryaccept(int argc, VALUE *argv, VALUE self)
362 struct accept_args a;
364 a.addr = NULL;
365 a.addrlen = NULL;
366 prepare_accept(&a, self, argc, argv);
367 return my_accept(&a, 1);
371 * call-seq:
373 * server = Kgio::UNIXServer.new("/path/to/unix/socket")
374 * server.kgio_accept -> Kgio::Socket or nil
375 * server.kgio_accept(klass = MySocket) -> MySocket or nil
376 * server.kgio_accept(nil, flags) -> Kgio::Socket or nil
378 * Initiates a blocking accept and returns a generic Kgio::Socket
379 * object with the kgio_addr attribute set (to the value of
380 * Kgio::LOCALHOST) on success.
382 * On Ruby implementations using native threads, this can use a blocking
383 * accept(2) (or accept4(2)) system call to avoid thundering herds.
385 * An optional +klass+ argument may be specified to override the
386 * Kgio::Socket-class on a successful return value.
388 * An optional +flags+ argument may also be specifed to override the
389 * value of +Kgio.accept_cloexec+ and +Kgio.accept_nonblock+. +flags+
390 * is a bitmask that may contain any combination of:
392 * - Fcntl::FD_CLOEXEC - close-on-exec flag
393 * - IO::NONBLOCK - non-blocking flag
395 static VALUE unix_accept(int argc, VALUE *argv, VALUE self)
397 struct accept_args a;
399 a.addr = NULL;
400 a.addrlen = NULL;
401 prepare_accept(&a, self, argc, argv);
402 return my_accept(&a, 0);
406 * call-seq:
408 * Kgio.accept_cloexec? -> true or false
410 * Returns true if newly accepted Kgio::Sockets are created with the
411 * FD_CLOEXEC file descriptor flag, false if not.
413 static VALUE get_cloexec(VALUE mod)
415 return (accept4_flags & SOCK_CLOEXEC) == SOCK_CLOEXEC ? Qtrue : Qfalse;
420 * call-seq:
422 * Kgio.accept_nonblock? -> true or false
424 * Returns true if newly accepted Kgio::Sockets are created with the
425 * O_NONBLOCK file status flag, false if not.
427 static VALUE get_nonblock(VALUE mod)
429 return (accept4_flags & SOCK_NONBLOCK)==SOCK_NONBLOCK ? Qtrue : Qfalse;
433 * call-seq:
435 * Kgio.accept_cloexec = true
436 * Kgio.accept_cloexec = false
438 * Sets whether or not Kgio::Socket objects created by
439 * TCPServer#kgio_accept,
440 * TCPServer#kgio_tryaccept,
441 * UNIXServer#kgio_accept,
442 * and UNIXServer#kgio_tryaccept
443 * default to being created with the FD_CLOEXEC file descriptor flag.
445 * This is on by default, as there is little reason to deal to enable
446 * it for client sockets on a socket server.
448 static VALUE set_cloexec(VALUE mod, VALUE boolean)
450 switch (TYPE(boolean)) {
451 case T_TRUE:
452 accept4_flags |= SOCK_CLOEXEC;
453 return boolean;
454 case T_FALSE:
455 accept4_flags &= ~SOCK_CLOEXEC;
456 return boolean;
458 rb_raise(rb_eTypeError, "not true or false");
459 return Qnil;
463 * call-seq:
465 * Kgio.accept_nonblock = true
466 * Kgio.accept_nonblock = false
468 * Sets whether or not Kgio::Socket objects created by
469 * TCPServer#kgio_accept,
470 * TCPServer#kgio_tryaccept,
471 * UNIXServer#kgio_accept,
472 * and UNIXServer#kgio_tryaccept
473 * are created with the O_NONBLOCK file status flag.
475 * This defaults to +false+ for GNU/Linux where MSG_DONTWAIT is
476 * available (and on newer GNU/Linux, accept4() may also set
477 * the non-blocking flag. This defaults to +true+ on non-GNU/Linux
478 * systems.
480 static VALUE set_nonblock(VALUE mod, VALUE boolean)
482 switch (TYPE(boolean)) {
483 case T_TRUE:
484 accept4_flags |= SOCK_NONBLOCK;
485 return boolean;
486 case T_FALSE:
487 accept4_flags &= ~SOCK_NONBLOCK;
488 return boolean;
490 rb_raise(rb_eTypeError, "not true or false");
491 return Qnil;
494 void init_kgio_accept(void)
496 VALUE cUNIXServer, cTCPServer;
497 VALUE mKgio = rb_define_module("Kgio");
499 localhost = rb_const_get(mKgio, rb_intern("LOCALHOST"));
500 cKgio_Socket = rb_const_get(mKgio, rb_intern("Socket"));
501 cClientSocket = cKgio_Socket;
502 mSocketMethods = rb_const_get(mKgio, rb_intern("SocketMethods"));
504 rb_define_method(mSocketMethods, "kgio_addr!", addr_bang, 0);
506 rb_define_singleton_method(mKgio, "accept_cloexec?", get_cloexec, 0);
507 rb_define_singleton_method(mKgio, "accept_cloexec=", set_cloexec, 1);
508 rb_define_singleton_method(mKgio, "accept_nonblock?", get_nonblock, 0);
509 rb_define_singleton_method(mKgio, "accept_nonblock=", set_nonblock, 1);
510 rb_define_singleton_method(mKgio, "accept_class=", set_accepted, 1);
511 rb_define_singleton_method(mKgio, "accept_class", get_accepted, 0);
514 * Document-class: Kgio::UNIXServer
516 * Kgio::UNIXServer should be used in place of the plain UNIXServer
517 * when kgio_accept and kgio_tryaccept methods are needed.
519 cUNIXServer = rb_const_get(rb_cObject, rb_intern("UNIXServer"));
520 cUNIXServer = rb_define_class_under(mKgio, "UNIXServer", cUNIXServer);
521 rb_define_method(cUNIXServer, "kgio_tryaccept", unix_tryaccept, -1);
522 rb_define_method(cUNIXServer, "kgio_accept", unix_accept, -1);
525 * Document-class: Kgio::TCPServer
527 * Kgio::TCPServer should be used in place of the plain TCPServer
528 * when kgio_accept and kgio_tryaccept methods are needed.
530 cTCPServer = rb_const_get(rb_cObject, rb_intern("TCPServer"));
531 cTCPServer = rb_define_class_under(mKgio, "TCPServer", cTCPServer);
533 rb_define_method(cTCPServer, "kgio_tryaccept", tcp_tryaccept, -1);
534 rb_define_method(cTCPServer, "kgio_accept", tcp_accept, -1);
535 init_sock_for_fd();
536 iv_kgio_addr = rb_intern("@kgio_addr");