mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
r22830: merged the latest lib/events updates from ctdb to Samba4. This
includes a new EVENT_FD_AUTOCLOSE flag that prevents race conditions where code using fd events might close a fd before releasing the struct fd_event. That causes headaches for epoll.
This commit is contained in:
parent
2c9d0b57f9
commit
f1ad216de1
@ -5,6 +5,7 @@ AC_CHECK_HEADERS(sys/epoll.h)
|
||||
AC_CHECK_FUNCS(epoll_create)
|
||||
if test x"$ac_cv_header_sys_epoll_h" = x"yes" -a x"$ac_cv_func_epoll_create" = x"yes";then
|
||||
SMB_ENABLE(EVENTS_EPOLL,YES)
|
||||
AC_DEFINE(HAVE_EVENTS_EPOLL, 1, [Whether epoll is available])
|
||||
|
||||
# check for native Linux AIO interface
|
||||
AC_CHECK_HEADERS(libaio.h)
|
||||
|
@ -71,6 +71,8 @@ struct event_ops_list {
|
||||
/* list of registered event backends */
|
||||
static struct event_ops_list *event_backends;
|
||||
|
||||
static char *event_default_backend = NULL;
|
||||
|
||||
/*
|
||||
register an events backend
|
||||
*/
|
||||
@ -85,6 +87,15 @@ bool event_register_backend(const char *name, const struct event_ops *ops)
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
set the default event backend
|
||||
*/
|
||||
void event_set_default_backend(const char *backend)
|
||||
{
|
||||
if (event_default_backend) free(event_default_backend);
|
||||
event_default_backend = strdup(backend);
|
||||
}
|
||||
|
||||
/*
|
||||
initialise backends if not already done
|
||||
*/
|
||||
@ -99,7 +110,15 @@ static void event_backend_init(void)
|
||||
run_init_functions(shared_init);
|
||||
#else
|
||||
bool events_standard_init(void);
|
||||
bool events_select_init(void);
|
||||
events_select_init();
|
||||
events_standard_init();
|
||||
#if HAVE_EVENTS_EPOLL
|
||||
{
|
||||
bool events_epoll_init(void);
|
||||
events_epoll_init();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -169,6 +188,9 @@ struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char
|
||||
name = lp_parm_string(-1, "event", "backend");
|
||||
}
|
||||
#endif
|
||||
if (name == NULL) {
|
||||
name = event_default_backend;
|
||||
}
|
||||
if (name == NULL) {
|
||||
name = "standard";
|
||||
}
|
||||
@ -195,6 +217,9 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
|
||||
/*
|
||||
add a fd based event
|
||||
return NULL on failure (memory allocation error)
|
||||
|
||||
if flags contains EVENT_FD_AUTOCLOSE then the fd will be closed when
|
||||
the returned fd_event context is freed
|
||||
*/
|
||||
struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
|
||||
int fd, uint16_t flags, event_fd_handler_t handler,
|
||||
|
@ -46,6 +46,7 @@ typedef void (*event_aio_handler_t)(struct event_context *, struct aio_event *,
|
||||
struct event_context *event_context_init(TALLOC_CTX *mem_ctx);
|
||||
struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name);
|
||||
const char **event_backend_list(TALLOC_CTX *mem_ctx);
|
||||
void event_set_default_backend(const char *backend);
|
||||
|
||||
struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
|
||||
int fd, uint16_t flags, event_fd_handler_t handler,
|
||||
@ -79,6 +80,7 @@ struct event_context *event_context_find(TALLOC_CTX *mem_ctx);
|
||||
/* bits for file descriptor event flags */
|
||||
#define EVENT_FD_READ 1
|
||||
#define EVENT_FD_WRITE 2
|
||||
#define EVENT_FD_AUTOCLOSE 4
|
||||
|
||||
#define EVENT_FD_WRITEABLE(fde) \
|
||||
event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
|
||||
|
@ -361,6 +361,11 @@ static int aio_event_fd_destructor(struct fd_event *fde)
|
||||
|
||||
epoll_del_event(aio_ev, fde);
|
||||
|
||||
if (fde->flags & EVENT_FD_AUTOCLOSE) {
|
||||
close(fde->fd);
|
||||
fde->fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,9 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct fd_even
|
||||
ZERO_STRUCT(event);
|
||||
event.events = epoll_map_flags(fde->flags);
|
||||
event.data.ptr = fde;
|
||||
epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
|
||||
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) {
|
||||
DEBUG(0,("epoll_del_event failed! probable early close bug (%s)\n", strerror(errno)));
|
||||
}
|
||||
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
|
||||
}
|
||||
|
||||
@ -202,7 +204,7 @@ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct fd_e
|
||||
static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval *tvalp)
|
||||
{
|
||||
int ret, i;
|
||||
#define MAXEVENTS 8
|
||||
#define MAXEVENTS 32
|
||||
struct epoll_event events[MAXEVENTS];
|
||||
uint32_t destruction_count = ++epoll_ev->destruction_count;
|
||||
int timeout = -1;
|
||||
@ -306,6 +308,11 @@ static int epoll_event_fd_destructor(struct fd_event *fde)
|
||||
|
||||
epoll_del_event(epoll_ev, fde);
|
||||
|
||||
if (fde->flags & EVENT_FD_AUTOCLOSE) {
|
||||
close(fde->fd);
|
||||
fde->fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,11 @@ static int oop_event_fd_destructor(struct fd_event *fde)
|
||||
if (fde->flags & EVENT_FD_WRITE)
|
||||
oop->cancel_fd(oop, fde->fd, OOP_WRITE);
|
||||
|
||||
if (fde->flags & EVENT_FD_AUTOCLOSE) {
|
||||
close(fde->fd);
|
||||
fde->fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,11 @@ static int select_event_fd_destructor(struct fd_event *fde)
|
||||
DLIST_REMOVE(select_ev->fd_events, fde);
|
||||
select_ev->destruction_count++;
|
||||
|
||||
if (fde->flags & EVENT_FD_AUTOCLOSE) {
|
||||
close(fde->fd);
|
||||
fde->fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "system/filesys.h"
|
||||
#include "system/select.h" /* needed for WITH_EPOLL */
|
||||
#include "system/select.h" /* needed for HAVE_EVENTS_EPOLL */
|
||||
#include "lib/util/dlinklist.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/events/events_internal.h"
|
||||
@ -61,7 +61,7 @@ struct std_event_context {
|
||||
};
|
||||
|
||||
/* use epoll if it is available */
|
||||
#if WITH_EPOLL
|
||||
#if HAVE_EVENTS_EPOLL
|
||||
/*
|
||||
called when a epoll call fails, and we should fallback
|
||||
to using select
|
||||
@ -229,15 +229,15 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv
|
||||
timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
|
||||
}
|
||||
|
||||
if (epoll_ev->ev->num_signal_handlers &&
|
||||
common_event_check_signal(epoll_ev->ev)) {
|
||||
if (std_ev->ev->num_signal_handlers &&
|
||||
common_event_check_signal(std_ev->ev)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
|
||||
|
||||
if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) {
|
||||
if (common_event_check_signal(epoll_ev->ev)) {
|
||||
if (ret == -1 && errno == EINTR && std_ev->ev->num_signal_handlers) {
|
||||
if (common_event_check_signal(std_ev->ev)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -353,6 +353,11 @@ static int std_event_fd_destructor(struct fd_event *fde)
|
||||
|
||||
epoll_del_event(std_ev, fde);
|
||||
|
||||
if (fde->flags & EVENT_FD_AUTOCLOSE) {
|
||||
close(fde->fd);
|
||||
fde->fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
11
source/lib/events/libevents.m4
Normal file
11
source/lib/events/libevents.m4
Normal file
@ -0,0 +1,11 @@
|
||||
EVENTS_OBJ="lib/events/events.o lib/events/events_select.o lib/events/events_signal.o lib/events/events_timed.o lib/events/events_standard.o"
|
||||
|
||||
AC_CHECK_HEADERS(sys/epoll.h)
|
||||
AC_CHECK_FUNCS(epoll_create)
|
||||
|
||||
if test x"$ac_cv_header_sys_epoll_h" = x"yes" -a x"$ac_cv_func_epoll_create" = x"yes"; then
|
||||
EVENTS_OBJ="$EVENTS_OBJ lib/events/events_epoll.o"
|
||||
AC_DEFINE(HAVE_EVENTS_EPOLL, 1, [Whether epoll available])
|
||||
fi
|
||||
|
||||
AC_SUBST(EVENTS_OBJ)
|
Loading…
Reference in New Issue
Block a user