document this parameter better
[beanstalkd.git] / sock.c
blob1f71434f3cb929b489e2f491a269f3c478d5666a
1 // Copyright 2011 Keith Rarick. See file COPYING for details.
3 #include <stdlib.h>
4 #include <sys/resource.h>
5 #include <event.h>
6 #include "dat.h"
8 static void handleev(const int fd, const short ev, Socket *s);
9 static void nudge_fd_limit();
10 static Handle tick;
11 static void *tickval;
13 static struct timeval ival;
16 void
17 sockinit(Handle f, void *x, int64 i)
19 tick = f;
20 tickval = x;
21 init_timeval(&ival, i);
22 event_init();
23 nudge_fd_limit();
27 int
28 sockwant(Socket *s, int rw)
30 int r;
32 if (s->added) {
33 r = event_del(&s->evq);
34 if (r == -1) {
35 return -1;
38 s->added = 1;
39 if (rw) {
40 int mask = 0;
42 switch (rw) {
43 case 't':
44 // fake a global timeout with libevent
45 event_set(&s->evq, s->fd, EV_READ|EV_PERSIST, (evh)handleev, s);
46 return event_add(&s->evq, &ival);
47 case 'r':
48 mask = EV_READ;
49 break;
50 case 'w':
51 mask = EV_WRITE;
52 break;
54 event_set(&s->evq, s->fd, mask|EV_PERSIST, (evh)handleev, s);
55 return event_add(&s->evq, 0);
57 return 0;
61 void
62 sockmain()
64 event_dispatch();
68 static void
69 handleev(const int fd, const short ev, Socket *s)
71 switch (ev) {
72 case EV_TIMEOUT:
73 // libevent removes the fd if it timed out, so put it back
74 event_add(&s->evq, &ival);
75 tick(tickval, 0);
76 break;
77 case EV_READ:
78 s->f(s->x, 'r');
79 break;
80 case EV_WRITE:
81 s->f(s->x, 'w');
82 break;
87 /* This is a workaround for a mystifying workaround in libevent's epoll
88 * implementation. The epoll_init() function creates an epoll fd with space to
89 * handle RLIMIT_NOFILE - 1 fds, accompanied by the following puzzling comment:
90 * "Solaris is somewhat retarded - it's important to drop backwards
91 * compatibility when making changes. So, don't dare to put rl.rlim_cur here."
92 * This is presumably to work around a bug in Solaris, but it has the
93 * unfortunate side-effect of causing epoll_ctl() (and, therefore, event_add())
94 * to fail for a valid fd if we have hit the limit of open fds. That makes it
95 * hard to provide reasonable behavior in that situation. So, let's reduce the
96 * real value of RLIMIT_NOFILE by one, after epoll_init() has run. */
97 static void
98 nudge_fd_limit()
100 int r;
101 struct rlimit rl;
103 r = getrlimit(RLIMIT_NOFILE, &rl);
104 if (r != 0) twarn("getrlimit(RLIMIT_NOFILE)"), exit(2);
106 rl.rlim_cur--;
108 r = setrlimit(RLIMIT_NOFILE, &rl);
109 if (r != 0) twarn("setrlimit(RLIMIT_NOFILE)"), exit(2);