[core] isolate fdevent subsystem
fdevent.c no longer directly uses struct server *srv srv->srvconf.max_fds (if set) is used to set rlimits set max_conns in server.c after fdevent_init(), which sets srv->max_fds using srv->srvconf.max_fds (if set) as input hint
This commit is contained in:
parent
6dfe0b9a16
commit
8588772caa
|
@ -355,7 +355,6 @@ struct server {
|
|||
server_socket_array srv_sockets_inherited;
|
||||
buffer_plugin plugins;
|
||||
|
||||
int event_handler;
|
||||
time_t startup_ts;
|
||||
|
||||
uid_t uid;
|
||||
|
|
|
@ -2064,7 +2064,8 @@ int config_set_defaults(server *srv) {
|
|||
specific_config *s = &((config_data_base *)srv->config_data_base)->defaults;
|
||||
struct stat st1, st2;
|
||||
|
||||
if (0 != fdevent_config(srv)) return -1;
|
||||
if (fdevent_config(&srv->srvconf.event_handler, srv->errh) <= 0)
|
||||
return -1;
|
||||
|
||||
if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
|
||||
if (-1 == stat(srv->srvconf.changeroot->ptr, &st1)) {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "fdevent_impl.h"
|
||||
#include "fdevent.h"
|
||||
#include "base.h"
|
||||
#include "buffer.h"
|
||||
#include "log.h"
|
||||
|
||||
|
@ -24,7 +23,7 @@ static int use_sock_cloexec;
|
|||
static int use_sock_nonblock;
|
||||
#endif
|
||||
|
||||
int fdevent_config(server *srv) {
|
||||
int fdevent_config(const char **event_handler_name, log_error_st *errh) {
|
||||
static const struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
|
||||
{
|
||||
/* - epoll is most reliable
|
||||
|
@ -56,57 +55,45 @@ int fdevent_config(server *srv) {
|
|||
{ FDEVENT_HANDLER_UNSET, NULL }
|
||||
};
|
||||
|
||||
if (NULL == srv->srvconf.event_handler) {
|
||||
const char * event_handler = *event_handler_name;
|
||||
fdevent_handler_t et = FDEVENT_HANDLER_UNSET;
|
||||
|
||||
if (NULL == event_handler) {
|
||||
/* choose a good default
|
||||
*
|
||||
* the event_handler list is sorted by 'goodness'
|
||||
* taking the first available should be the best solution
|
||||
*/
|
||||
srv->event_handler = event_handlers[0].et;
|
||||
et = event_handlers[0].et;
|
||||
*event_handler_name = event_handlers[0].name;
|
||||
|
||||
if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
if (FDEVENT_HANDLER_UNSET == et) {
|
||||
log_error(errh, __FILE__, __LINE__,
|
||||
"sorry, there is no event handler for this system");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
srv->srvconf.event_handler = event_handlers[0].name;
|
||||
} else {
|
||||
/*
|
||||
* User override
|
||||
*/
|
||||
|
||||
for (uint32_t i = 0; event_handlers[i].name; ++i) {
|
||||
if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler)) {
|
||||
srv->event_handler = event_handlers[i].et;
|
||||
if (0 == strcmp(event_handlers[i].name, event_handler)) {
|
||||
et = event_handlers[i].et;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
if (FDEVENT_HANDLER_UNSET == et) {
|
||||
log_error(errh, __FILE__, __LINE__,
|
||||
"the selected event-handler in unknown or not supported: %s",
|
||||
srv->srvconf.event_handler);
|
||||
event_handler);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FDEVENT_USE_SELECT
|
||||
if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
|
||||
/* select limits itself
|
||||
*
|
||||
* as it is a hard limit and will lead to a segfault we add some safety
|
||||
* */
|
||||
srv->max_fds = FD_SETSIZE - 200;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
srv->max_fds = 4096;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return et;
|
||||
}
|
||||
|
||||
const char * fdevent_show_event_handlers(void) {
|
||||
|
@ -150,10 +137,13 @@ const char * fdevent_show_event_handlers(void) {
|
|||
;
|
||||
}
|
||||
|
||||
fdevents *fdevent_init(server *srv) {
|
||||
fdevents * fdevent_init(const char *event_handler, int *max_fds, int *cur_fds, log_error_st *errh) {
|
||||
fdevents *ev;
|
||||
int type = srv->event_handler;
|
||||
uint32_t maxfds;
|
||||
uint32_t maxfds = (0 != *max_fds)
|
||||
? (uint32_t)*max_fds
|
||||
: 4096;
|
||||
int type = fdevent_config(&event_handler, errh);
|
||||
if (type <= 0) return NULL;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
/* Test if SOCK_CLOEXEC is supported by kernel.
|
||||
|
@ -180,20 +170,25 @@ fdevents *fdevent_init(server *srv) {
|
|||
#endif
|
||||
|
||||
#ifdef FDEVENT_USE_SELECT
|
||||
/* select limits itself
|
||||
* as it is a hard limit and will lead to a segfault we add some safety
|
||||
* */
|
||||
if (type == FDEVENT_HANDLER_SELECT) {
|
||||
if (srv->max_fds > (int)FD_SETSIZE - 200) {
|
||||
srv->max_fds = (int)FD_SETSIZE - 200;
|
||||
}
|
||||
if (maxfds > (uint32_t)FD_SETSIZE - 200)
|
||||
maxfds = (uint32_t)FD_SETSIZE - 200;
|
||||
}
|
||||
#endif
|
||||
maxfds = srv->max_fds + 1; /*(+1 for event-handler fd)*/
|
||||
*max_fds = (int)maxfds;
|
||||
++maxfds; /*(+1 for event-handler fd)*/
|
||||
|
||||
ev = calloc(1, sizeof(*ev));
|
||||
force_assert(NULL != ev);
|
||||
ev->srv = srv;
|
||||
ev->errh = errh;
|
||||
ev->cur_fds = cur_fds;
|
||||
ev->event_handler = event_handler;
|
||||
ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
|
||||
if (NULL == ev->fdarray) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
log_error(ev->errh, __FILE__, __LINE__,
|
||||
"server.max-fds too large? (%u)", maxfds-1);
|
||||
free(ev);
|
||||
return NULL;
|
||||
|
@ -244,10 +239,10 @@ fdevents *fdevent_init(server *srv) {
|
|||
free(ev->fdarray);
|
||||
free(ev);
|
||||
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
log_error(errh, __FILE__, __LINE__,
|
||||
"event-handler failed: %s; "
|
||||
"try to set server.event-handler = \"poll\" or \"select\"",
|
||||
srv->srvconf.event_handler);
|
||||
event_handler);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -270,11 +265,10 @@ void fdevent_free(fdevents *ev) {
|
|||
int fdevent_reset(fdevents *ev) {
|
||||
int rc = (NULL != ev->reset) ? ev->reset(ev) : 0;
|
||||
if (-1 == rc) {
|
||||
const char *event_handler = ev->srv->srvconf.event_handler;
|
||||
log_error(ev->srv->errh, __FILE__, __LINE__,
|
||||
log_error(ev->errh, __FILE__, __LINE__,
|
||||
"event-handler failed: %s; "
|
||||
"try to set server.event-handler = \"poll\" or \"select\"",
|
||||
event_handler ? event_handler : "");
|
||||
ev->event_handler ? ev->event_handler : "");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -318,7 +312,6 @@ void fdevent_sched_close(fdevents *ev, int fd, int issock) {
|
|||
}
|
||||
|
||||
static void fdevent_sched_run(fdevents *ev) {
|
||||
server *srv = ev->srv;
|
||||
for (fdnode *fdn = ev->pendclose; fdn; ) {
|
||||
int fd, rc;
|
||||
fdnode *fdn_tmp;
|
||||
|
@ -339,10 +332,10 @@ static void fdevent_sched_run(fdevents *ev) {
|
|||
#endif
|
||||
|
||||
if (0 != rc) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__, "close failed %d", fd);
|
||||
log_perror(ev->errh, __FILE__, __LINE__, "close failed %d", fd);
|
||||
}
|
||||
else {
|
||||
--srv->cur_fds;
|
||||
--(*ev->cur_fds);
|
||||
}
|
||||
|
||||
fdn_tmp = fdn;
|
||||
|
@ -371,7 +364,7 @@ static int fdevent_fdnode_event_unsetter_retry(fdevents *ev, fdnode *fdn) {
|
|||
/*case ENOMEM:*/
|
||||
default:
|
||||
/* unrecoverable error; might leak fd */
|
||||
log_perror(ev->srv->errh, __FILE__, __LINE__,
|
||||
log_perror(ev->errh, __FILE__, __LINE__,
|
||||
"fdevent event_del failed on fd %d", fdn->fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -404,7 +397,7 @@ static int fdevent_fdnode_event_setter_retry(fdevents *ev, fdnode *fdn, int even
|
|||
/*case ENOMEM:*/
|
||||
default:
|
||||
/* unrecoverable error */
|
||||
log_perror(ev->srv->errh, __FILE__, __LINE__,
|
||||
log_perror(ev->errh, __FILE__, __LINE__,
|
||||
"fdevent event_set failed on fd %d", fdn->fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -445,7 +438,7 @@ int fdevent_poll(fdevents *ev, int timeout_ms) {
|
|||
if (n >= 0)
|
||||
fdevent_sched_run(ev);
|
||||
else if (errno != EINTR)
|
||||
log_perror(ev->srv->errh, __FILE__, __LINE__, "fdevent_poll failed");
|
||||
log_perror(ev->errh, __FILE__, __LINE__, "fdevent_poll failed");
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#define _FDEVENT_H_
|
||||
#include "first.h"
|
||||
|
||||
#include "base_decls.h"
|
||||
#include "base_decls.h" /* handler_t */
|
||||
|
||||
struct log_error_st; /* declaration */
|
||||
struct fdevents; /* declaration */
|
||||
typedef struct fdevents fdevents;
|
||||
|
||||
|
@ -46,13 +47,13 @@ struct fdnode_st {
|
|||
#define FDEVENT_STREAM_RESPONSE_POLLRDHUP BV(15)
|
||||
|
||||
__attribute_cold__
|
||||
int fdevent_config(server *srv);
|
||||
int fdevent_config(const char **event_handler_name, struct log_error_st *errh);
|
||||
|
||||
__attribute_cold__
|
||||
const char * fdevent_show_event_handlers(void);
|
||||
|
||||
__attribute_cold__
|
||||
fdevents *fdevent_init(struct server *srv);
|
||||
fdevents * fdevent_init(const char *event_handler, int *max_fds, int *cur_fds, struct log_error_st *errh);
|
||||
|
||||
__attribute_cold__
|
||||
int fdevent_reset(fdevents *ev); /* "init" after fork() */
|
||||
|
|
|
@ -82,7 +82,8 @@ struct fdevents {
|
|||
int (*event_del)(struct fdevents *ev, fdnode *fdn);
|
||||
int (*poll)(struct fdevents *ev, int timeout_ms);
|
||||
|
||||
struct server *srv;
|
||||
log_error_st *errh;
|
||||
int *cur_fds;
|
||||
uint32_t maxfds;
|
||||
#ifdef FDEVENT_USE_LINUX_EPOLL
|
||||
int epoll_fd;
|
||||
|
@ -125,6 +126,7 @@ struct fdevents {
|
|||
|
||||
int (*reset)(struct fdevents *ev);
|
||||
void (*free)(struct fdevents *ev);
|
||||
const char *event_handler;
|
||||
fdevent_handler_t type;
|
||||
};
|
||||
|
||||
|
|
|
@ -64,8 +64,7 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) {
|
|||
int revents = ev->port_events[i].portev_events;
|
||||
if (0 == ((uintptr_t)fdn & 0x3)) {
|
||||
if (port_associate(pfd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud) < 0) {
|
||||
log_error(ev->srv->errh, __FILE__, __LINE__,
|
||||
"port_associate failed");
|
||||
log_error(ev->errh,__FILE__,__LINE__,"port_associate failed");
|
||||
}
|
||||
(*fdn->handler)(fdn->ctx, revents);
|
||||
}
|
||||
|
|
43
src/server.c
43
src/server.c
|
@ -935,10 +935,11 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
srv->max_fds = rlim.rlim_cur;
|
||||
/*(default upper limit of 4k if server.max-fds not specified)*/
|
||||
if (i_am_root && 0 == srv->srvconf.max_fds && rlim.rlim_cur > 4096)
|
||||
srv->max_fds = 4096;
|
||||
/*(default upper limit of 4k if server.max-fds not specified)*/
|
||||
if (0 == srv->srvconf.max_fds)
|
||||
srv->srvconf.max_fds = (rlim.rlim_cur <= 4096)
|
||||
? (unsigned short)rlim.rlim_cur
|
||||
: 4096;
|
||||
|
||||
/* set core file rlimit, if enable_cores is set */
|
||||
if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
|
||||
|
@ -1046,21 +1047,6 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
#endif
|
||||
}
|
||||
|
||||
/* set max-conns */
|
||||
if (srv->srvconf.max_conns > srv->max_fds/2) {
|
||||
/* we can't have more connections than max-fds/2 */
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"can't have more connections than fds/2: %hu %d",
|
||||
srv->srvconf.max_conns, srv->max_fds);
|
||||
srv->max_conns = srv->max_fds/2;
|
||||
} else if (srv->srvconf.max_conns) {
|
||||
/* otherwise respect the wishes of the user */
|
||||
srv->max_conns = srv->srvconf.max_conns;
|
||||
} else {
|
||||
/* or use the default: we really don't want to hit max-fds */
|
||||
srv->max_conns = srv->max_fds/3;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
/* network is up, let's daemonize ourself */
|
||||
if (0 == srv->srvconf.dont_daemonize && 0 == graceful_restart) {
|
||||
|
@ -1301,7 +1287,9 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (NULL == (srv->ev = fdevent_init(srv))) {
|
||||
srv->max_fds = (int)srv->srvconf.max_fds;
|
||||
srv->ev = fdevent_init(srv->srvconf.event_handler, &srv->max_fds, &srv->cur_fds, srv->errh);
|
||||
if (NULL == srv->ev) {
|
||||
log_error(srv->errh, __FILE__, __LINE__, "fdevent_init failed");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1309,6 +1297,21 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
srv->max_fds_lowat = srv->max_fds * 8 / 10;
|
||||
srv->max_fds_hiwat = srv->max_fds * 9 / 10;
|
||||
|
||||
/* set max-conns */
|
||||
if (srv->srvconf.max_conns > srv->max_fds/2) {
|
||||
/* we can't have more connections than max-fds/2 */
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"can't have more connections than fds/2: %hu %d",
|
||||
srv->srvconf.max_conns, srv->max_fds);
|
||||
srv->max_conns = srv->max_fds/2;
|
||||
} else if (srv->srvconf.max_conns) {
|
||||
/* otherwise respect the wishes of the user */
|
||||
srv->max_conns = srv->srvconf.max_conns;
|
||||
} else {
|
||||
/* or use the default: we really don't want to hit max-fds */
|
||||
srv->max_conns = srv->max_fds/3;
|
||||
}
|
||||
|
||||
/* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
|
|
Loading…
Reference in New Issue