summaryrefslogtreecommitdiff
path: root/source4/lib/events
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2007-05-14 00:57:48 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:52:21 -0500
commitecc54f900fa6aaf1b97ef85b1101cf7badf33cec (patch)
tree4985d6817c5b8e052fb4e0a3946a638697b602a0 /source4/lib/events
parentbc02bba4499b7f6c78dc5db0610fe4f4d238829a (diff)
downloadsamba-ecc54f900fa6aaf1b97ef85b1101cf7badf33cec.tar.gz
samba-ecc54f900fa6aaf1b97ef85b1101cf7badf33cec.tar.bz2
samba-ecc54f900fa6aaf1b97ef85b1101cf7badf33cec.zip
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 used to be commit f1ad216de13b154a1f8747a44b0970dcc47a784a)
Diffstat (limited to 'source4/lib/events')
-rw-r--r--source4/lib/events/config.m41
-rw-r--r--source4/lib/events/events.c25
-rw-r--r--source4/lib/events/events.h2
-rw-r--r--source4/lib/events/events_aio.c5
-rw-r--r--source4/lib/events/events_epoll.c11
-rw-r--r--source4/lib/events/events_liboop.c5
-rw-r--r--source4/lib/events/events_select.c5
-rw-r--r--source4/lib/events/events_standard.c17
-rw-r--r--source4/lib/events/libevents.m411
9 files changed, 74 insertions, 8 deletions
diff --git a/source4/lib/events/config.m4 b/source4/lib/events/config.m4
index c65ff91b17..180b58cbc6 100644
--- a/source4/lib/events/config.m4
+++ b/source4/lib/events/config.m4
@@ -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)
diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c
index 3a81b55bd9..5b36e70ac0 100644
--- a/source4/lib/events/events.c
+++ b/source4/lib/events/events.c
@@ -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
*/
@@ -86,6 +88,15 @@ bool event_register_backend(const char *name, const struct event_ops *ops)
}
/*
+ 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
*/
static void event_backend_init(void)
@@ -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
}
@@ -170,6 +189,9 @@ struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char
}
#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,
diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h
index 94dc56055c..42d67c31bf 100644
--- a/source4/lib/events/events.h
+++ b/source4/lib/events/events.h
@@ -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)
diff --git a/source4/lib/events/events_aio.c b/source4/lib/events/events_aio.c
index 0eadcf5fec..204b749332 100644
--- a/source4/lib/events/events_aio.c
+++ b/source4/lib/events/events_aio.c
@@ -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;
}
diff --git a/source4/lib/events/events_epoll.c b/source4/lib/events/events_epoll.c
index 2f879cc410..b553b6fd49 100644
--- a/source4/lib/events/events_epoll.c
+++ b/source4/lib/events/events_epoll.c
@@ -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;
}
diff --git a/source4/lib/events/events_liboop.c b/source4/lib/events/events_liboop.c
index 96bdafd956..cc9047b4eb 100644
--- a/source4/lib/events/events_liboop.c
+++ b/source4/lib/events/events_liboop.c
@@ -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;
}
diff --git a/source4/lib/events/events_select.c b/source4/lib/events/events_select.c
index b2f9cacf5f..55b477bfa7 100644
--- a/source4/lib/events/events_select.c
+++ b/source4/lib/events/events_select.c
@@ -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;
}
diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c
index dcf890ac12..799b19813a 100644
--- a/source4/lib/events/events_standard.c
+++ b/source4/lib/events/events_standard.c
@@ -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;
}
diff --git a/source4/lib/events/libevents.m4 b/source4/lib/events/libevents.m4
new file mode 100644
index 0000000000..99a47dcc54
--- /dev/null
+++ b/source4/lib/events/libevents.m4
@@ -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)