[PATCH] Change tevent "standard" backend to fall back from epoll -> poll
Stefan (metze) Metzmacher
metze at samba.org
Thu Feb 14 08:04:34 MST 2013
Hi Jeremy,
> Second attempt :-). This is the original patchset
> forward ported to master after Volker and Metze fixed
> the issues with the poll backend.
>
> Please review and push to master if you're happy with it !
I reviewed it and made some changes to it to fix some details
and make it easier to understand for me.
- I added a replay flag to epoll_panic() to indicate if it was called
from before calling an event handler or from within an event handler.
We should only call loop_once() of the poll backend if epoll_panic
was called before calling an event handler.
tevent_loop_once() should only trigger just one event handler.
- I introduced a 'struct std_event_glue' instead of using
tricks with const struct tevent_ops **
I've tested the fallback with the last two HACK patches,
which are reverted again and should not reach master.
I'm currently doing private autobuilds with and without the hack patches.
metze
-------------- next part --------------
From 8389c04ade90ebf37ad19f9e7d4c5d4ad88dd175 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:36:52 -0800
Subject: [PATCH 01/17] tevent: Preparing to fix "standard" backend fallback.
Initialize standard after epoll.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index fa842e4..e307dba 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -115,10 +115,10 @@ static void tevent_backend_init(void)
tevent_select_init();
tevent_poll_init();
tevent_poll_mt_init();
- tevent_standard_init();
#ifdef HAVE_EPOLL
tevent_epoll_init();
#endif
+ tevent_standard_init();
}
/*
--
1.7.9.5
From 9be7b5ee2e4746c121779291a84395012597689f Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:38:01 -0800
Subject: [PATCH 02/17] tevent: Ensure we return after every call to
epoll_panic().
Currently we can't return from this, but the new fallback
code will change this.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 5f93de2..8e7bc4d 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -152,6 +152,7 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed");
+ return;
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
@@ -201,6 +202,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed");
+ return;
}
/* only if we want to read we want to tell the event handler about errors */
--
1.7.9.5
From f0737d466cb3a085fe1e11e6713bf6ddedfd1b04 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 10:58:55 +0100
Subject: [PATCH 03/17] tevent: pass 'bool replay' to epoll_panic()
A fallback panic handler will need to know if
there was an error while waiting for events
(replay=true) or if the error happened on modify
(replay=false).
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 8e7bc4d..c7936d3 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -44,7 +44,8 @@ struct epoll_event_context {
/*
called when a epoll call fails
*/
-static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason)
+static void epoll_panic(struct epoll_event_context *epoll_ev,
+ const char *reason, bool replay)
{
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"%s (%s) - calling abort()\n", reason, strerror(errno));
@@ -151,7 +152,7 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
- epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed");
+ epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false);
return;
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
@@ -201,7 +202,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
- epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed");
+ epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false);
return;
}
@@ -277,7 +278,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
}
if (ret == -1 && errno != EINTR) {
- epoll_panic(epoll_ev, "epoll_wait() failed");
+ epoll_panic(epoll_ev, "epoll_wait() failed", true);
return -1;
}
@@ -293,7 +294,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
uint16_t flags = 0;
if (fde == NULL) {
- epoll_panic(epoll_ev, "epoll_wait() gave bad data");
+ epoll_panic(epoll_ev, "epoll_wait() gave bad data", true);
return -1;
}
if (events[i].events & (EPOLLHUP|EPOLLERR)) {
--
1.7.9.5
From b2de6eb0252bff3f2a08729a4004ead157cb1c67 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:43:39 -0800
Subject: [PATCH 04/17] tevent: Add an internal function
tevent_epoll_set_panic_fallback().
Can be set externally, allows us to fallback if epoll
fails at runtime.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 24 ++++++++++++++++++++++++
lib/tevent/tevent_internal.h | 3 +++
2 files changed, 27 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index c7936d3..8a48d1d 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -39,9 +39,33 @@ struct epoll_event_context {
int epoll_fd;
pid_t pid;
+
+ bool (*panic_fallback)(struct tevent_context *ev, bool replay);
};
/*
+ called to set the panic fallback function.
+*/
+_PRIVATE_ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
+ bool (*panic_fallback)(struct tevent_context *ev,
+ bool replay))
+{
+ struct epoll_event_context *epoll_ev;
+
+ if (ev->additional_data == NULL) {
+ return false;
+ }
+
+ epoll_ev = talloc_get_type(ev->additional_data,
+ struct epoll_event_context);
+ if (epoll_ev == NULL) {
+ return false;
+ }
+ epoll_ev->panic_fallback = panic_fallback;
+ return true;
+}
+
+/*
called when a epoll call fails
*/
static void epoll_panic(struct epoll_event_context *epoll_ev,
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index f09cf57..4e9cd69 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -318,6 +318,9 @@ bool tevent_poll_init(void);
bool tevent_poll_mt_init(void);
#ifdef HAVE_EPOLL
bool tevent_epoll_init(void);
+bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
+ bool (*panic_fallback)(struct tevent_context *ev,
+ bool replay));
#endif
void tevent_trace_point_callback(struct tevent_context *ev,
--
1.7.9.5
From c5e16ed2c8964a5a371fad947bd70a8cf0990bba Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:48:02 -0800
Subject: [PATCH 05/17] tevent: Plumb in the panic fallback code into the
epoll_panic() runtime call.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 8a48d1d..0ef1ffe 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -71,9 +71,26 @@ _PRIVATE_ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
static void epoll_panic(struct epoll_event_context *epoll_ev,
const char *reason, bool replay)
{
- tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
- "%s (%s) - calling abort()\n", reason, strerror(errno));
- abort();
+ struct tevent_context *ev = epoll_ev->ev;
+
+ if (epoll_ev->panic_fallback == NULL) {
+ tevent_debug(ev, TEVENT_DEBUG_FATAL,
+ "%s (%s) replay[%u] - calling abort()\n",
+ reason, strerror(errno), (unsigned)replay);
+ abort();
+ }
+
+ tevent_debug(ev, TEVENT_DEBUG_WARNING,
+ "%s (%s) replay[%u] - calling panic_fallback\n",
+ reason, strerror(errno), (unsigned)replay);
+
+ if (!epoll_ev->panic_fallback(ev, replay)) {
+ /* Fallback failed. */
+ tevent_debug(ev, TEVENT_DEBUG_FATAL,
+ "%s (%s) replay[%u] - calling abort()\n",
+ reason, strerror(errno), (unsigned)replay);
+ abort();
+ }
}
/*
--
1.7.9.5
From 964c96bb13b9e2dab4e240e03f07702f0659eba5 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:52:30 -0800
Subject: [PATCH 06/17] tevent: Add in some test code to allow the panic
fallback path to be tested.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 0ef1ffe..5a17331 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -43,6 +43,24 @@ struct epoll_event_context {
bool (*panic_fallback)(struct tevent_context *ev, bool replay);
};
+#ifdef TEST_PANIC_FALLBACK
+static int epoll_wait_panic_fallback(int epfd,
+ struct epoll_event *events,
+ int maxevents,
+ int timeout)
+{
+ /* 50% of the time, fail... */
+ if ((random() % 2) == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return epoll_wait(epfd, events, maxevents, timeout);
+}
+
+#define epoll_wait epoll_wait_panic_fallback
+#endif
+
/*
called to set the panic fallback function.
*/
--
1.7.9.5
From befe91aa7b8ba7bf2697b59918c9e370cc0bb97a Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:53:15 -0800
Subject: [PATCH 07/17] tevent: Add in the same tevent_re_initialise() fix
Metze put in the tevent_poll backend.
We might be called during tevent_re_initialise()
which means we need to free our old additional_data.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_epoll.c | 6 ++++++
lib/tevent/tevent_select.c | 6 ++++++
lib/tevent/tevent_standard.c | 6 ++++++
3 files changed, 18 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 5a17331..8696215 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -389,6 +389,12 @@ static int epoll_event_context_init(struct tevent_context *ev)
int ret;
struct epoll_event_context *epoll_ev;
+ /*
+ * We might be called during tevent_re_initialise()
+ * which means we need to free our old additional_data.
+ */
+ TALLOC_FREE(ev->additional_data);
+
epoll_ev = talloc_zero(ev, struct epoll_event_context);
if (!epoll_ev) return -1;
epoll_ev->ev = ev;
diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c
index c11f0e8..7e0c927 100644
--- a/lib/tevent/tevent_select.c
+++ b/lib/tevent/tevent_select.c
@@ -47,6 +47,12 @@ static int select_event_context_init(struct tevent_context *ev)
{
struct select_event_context *select_ev;
+ /*
+ * We might be called during tevent_re_initialise()
+ * which means we need to free our old additional_data.
+ */
+ TALLOC_FREE(ev->additional_data);
+
select_ev = talloc_zero(ev, struct select_event_context);
if (!select_ev) return -1;
select_ev->ev = ev;
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index 1e33720..938b223 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -348,6 +348,12 @@ static int std_event_context_init(struct tevent_context *ev)
{
struct std_event_context *std_ev;
+ /*
+ * We might be called during tevent_re_initialise()
+ * which means we need to free our old additional_data.
+ */
+ TALLOC_FREE(ev->additional_data);
+
std_ev = talloc_zero(ev, struct std_event_context);
if (!std_ev) return -1;
std_ev->ev = ev;
--
1.7.9.5
From 99a60209da8bb2ae5769e0e126d7d6e016192b94 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 10:56:58 -0800
Subject: [PATCH 08/17] tevent: Add a utility function
tevent_find_ops_byname().
Returns an event ops struct given a string name. Not
yet used, but will be part of the new "standard" fallback
code.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent.c | 22 ++++++++++++++++++++++
lib/tevent/tevent_internal.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index e307dba..6352471 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -121,6 +121,28 @@ static void tevent_backend_init(void)
tevent_standard_init();
}
+_PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
+{
+ struct tevent_ops_list *e;
+
+ tevent_backend_init();
+
+ if (name == NULL) {
+ name = tevent_default_backend;
+ }
+ if (name == NULL) {
+ name = "standard";
+ }
+
+ for (e = tevent_backends; e != NULL; e = e->next) {
+ if (0 == strcmp(e->name, name)) {
+ return e->ops;
+ }
+ }
+
+ return NULL;
+}
+
/*
list available backends
*/
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index 4e9cd69..fa6652c 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -265,6 +265,7 @@ struct tevent_context {
} tracing;
};
+const struct tevent_ops *tevent_find_ops_byname(const char *name);
int tevent_common_context_destructor(struct tevent_context *ev);
int tevent_common_loop_wait(struct tevent_context *ev,
--
1.7.9.5
From 4744433a68324e5781a47c1d04688a43d3329c56 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 09:29:57 +0100
Subject: [PATCH 09/17] tevent: make sure tevent_backend_init() only runs once
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index 6352471..669b778 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -112,6 +112,14 @@ void tevent_set_default_backend(const char *backend)
*/
static void tevent_backend_init(void)
{
+ static bool done;
+
+ if (done) {
+ return;
+ }
+
+ done = true;
+
tevent_select_init();
tevent_poll_init();
tevent_poll_mt_init();
--
1.7.9.5
From a3b0aebf1f6f5c0513502d629b42095848b8db29 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 09:30:31 +0100
Subject: [PATCH 10/17] tevent: make use of tevent_find_ops_byname() in
tevent_context_init_byname()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index 669b778..aa758de 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -273,23 +273,14 @@ struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
const char *name)
{
- struct tevent_ops_list *e;
-
- tevent_backend_init();
+ struct tevent_ops *ops;
- if (name == NULL) {
- name = tevent_default_backend;
- }
- if (name == NULL) {
- name = "standard";
+ ops = tevent_find_ops_byname(name);
+ if (ops == NULL) {
+ return NULL;
}
- for (e=tevent_backends;e;e=e->next) {
- if (strcmp(name, e->name) == 0) {
- return tevent_context_init_ops(mem_ctx, e->ops, NULL);
- }
- }
- return NULL;
+ return tevent_context_init_ops(mem_ctx, ops, NULL);
}
--
1.7.9.5
From 5d1a76b9c01e0e0902db06853dbfce067dde01ea Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 11:20:28 -0800
Subject: [PATCH 11/17] tevent: Add a private function
tevent_poll_event_add_fd_internal().
Not yet used, but will be called by the "standard"
fallback from epoll -> poll backends.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_internal.h | 3 +++
lib/tevent/tevent_poll.c | 16 ++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index fa6652c..8433333 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -316,6 +316,8 @@ void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se);
bool tevent_standard_init(void);
bool tevent_select_init(void);
bool tevent_poll_init(void);
+void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
+ struct tevent_fd *fde);
bool tevent_poll_mt_init(void);
#ifdef HAVE_EPOLL
bool tevent_epoll_init(void);
@@ -324,5 +326,6 @@ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
bool replay));
#endif
+
void tevent_trace_point_callback(struct tevent_context *ev,
enum tevent_trace_point);
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 5479f2f..89b3bbc 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -256,6 +256,22 @@ static void poll_event_schedule_immediate(struct tevent_immediate *im,
}
/*
+ Private function called by "standard" backend fallback.
+ Note this only allows fallback to "poll" backend, not "poll-mt".
+*/
+_PRIVATE_ void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
+ struct tevent_fd *fde)
+{
+ struct poll_event_context *poll_ev = talloc_get_type_abort(
+ ev->additional_data, struct poll_event_context);
+
+ fde->additional_flags = UINT64_MAX;
+ fde->additional_data = NULL;
+ DLIST_ADD(poll_ev->fresh, fde);
+ talloc_set_destructor(fde, poll_fresh_fde_destructor);
+}
+
+/*
add a fd based event
return NULL on failure (memory allocation error)
*/
--
1.7.9.5
From 964a8354baaf1f4e0f440cfc1a1e2912227d40c9 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 11:40:49 -0800
Subject: [PATCH 12/17] tevent: Add in the new implementation of "standard"
tevent backend.
Falls back cleanly from epoll -> poll, or uses poll if
epoll not available.
Signed-off-by: Jeremy Allison <jra at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_standard.c | 186 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 180 insertions(+), 6 deletions(-)
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index 938b223..0c72226 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -2,7 +2,8 @@
Unix SMB/CIFS implementation.
main select loop and event handling
Copyright (C) Andrew Tridgell 2003-2005
- Copyright (C) Stefan Metzmacher 2005-2009
+ Copyright (C) Stefan Metzmacher 2005-2013
+ Copyright (C) Jeremy Allison 2013
** NOTE! The following LGPL license applies to the tevent
** library. This does NOT imply that all of Samba is released
@@ -26,18 +27,17 @@
This is SAMBA's default event loop code
- we try to use epoll if configure detected support for it
- otherwise we use select()
+ otherwise we use poll()
- if epoll is broken on the system or the kernel doesn't support it
- at runtime we fallback to select()
+ at runtime we fallback to poll()
*/
#include "replace.h"
-#include "system/filesys.h"
-#include "system/select.h"
#include "tevent.h"
#include "tevent_util.h"
#include "tevent_internal.h"
+#if 0
struct std_event_context {
/* a pointer back to the generic event_context */
struct tevent_context *ev;
@@ -589,10 +589,184 @@ static const struct tevent_ops std_event_ops = {
.loop_once = std_event_loop_once,
.loop_wait = tevent_common_loop_wait,
};
+#endif
+
+struct std_event_glue {
+ const struct tevent_ops *epoll_ops;
+ const struct tevent_ops *poll_ops;
+ struct tevent_ops *glue_ops;
+ bool fallback_replay;
+};
+
+static int std_event_context_init(struct tevent_context *ev);
+
+static const struct tevent_ops std_event_ops = {
+ .context_init = std_event_context_init,
+};
+
+/*
+ If this function gets called. epoll failed at runtime.
+ Move us to using poll instead. If we return false here,
+ caller should abort().
+*/
+static bool std_fallback_to_poll(struct tevent_context *ev, bool replay)
+{
+ void *glue_ptr = talloc_parent(ev->ops);
+ struct std_event_glue *glue =
+ talloc_get_type_abort(glue_ptr,
+ struct std_event_glue);
+ int ret;
+ struct tevent_fd *fde;
+ struct tevent_fd *fde_next;
+
+ glue->fallback_replay = replay;
+
+ /* First switch all the ops to poll. */
+ glue->epoll_ops = NULL;
+ TALLOC_FREE(ev->additional_data);
+
+ /*
+ * Set custom_ops the same as poll.
+ */
+ *glue->glue_ops = *glue->poll_ops;
+ glue->glue_ops->context_init = std_event_context_init;
+ /* Next initialize the poll backend. */
+ ret = glue->poll_ops->context_init(ev);
+ if (ret != 0) {
+ return false;
+ }
+
+ /*
+ * Now we have to change all the existing file descriptor
+ * events from the epoll backend to the poll backend.
+ */
+ for (fde = ev->fd_events; fde; fde = fde_next) {
+ /*
+ * We must remove this fde off the ev->fd_events list.
+ */
+ fde_next = fde->next;
+
+ /* Remove from the ev->fd_events list. */
+ DLIST_REMOVE(ev->fd_events, fde);
+
+ /* Re-add this event as a poll backend event. */
+ tevent_poll_event_add_fd_internal(ev, fde);
+ }
+
+ return true;
+}
+
+static int std_event_loop_once(struct tevent_context *ev, const char *location)
+{
+ void *glue_ptr = talloc_parent(ev->ops);
+ struct std_event_glue *glue =
+ talloc_get_type_abort(glue_ptr,
+ struct std_event_glue);
+ int ret;
+
+ ret = glue->epoll_ops->loop_once(ev, location);
+ if (glue->epoll_ops != NULL) {
+ /* No fallback */
+ return ret;
+ }
+
+ if (!glue->fallback_replay) {
+ /*
+ * The problem happened while modifying an event.
+ * An event handler was triggered in this case
+ * and there is no need to call loop_once() again.
+ */
+ return ret;
+ }
+
+ return glue->poll_ops->loop_once(ev, location);
+}
+
+/*
+ Initialize the epoll backend and allow it to call a
+ switch function if epoll fails at runtime.
+*/
+static int std_event_context_init(struct tevent_context *ev)
+{
+ struct std_event_glue *glue;
+ int ret;
+
+ /*
+ * If this is the first initialization
+ * we need to set up the allocated ops
+ * pointers.
+ */
+
+ if (ev->ops == &std_event_ops) {
+ glue = talloc_zero(ev, struct std_event_glue);
+ if (glue == NULL) {
+ return -1;
+ }
+
+ glue->epoll_ops = tevent_find_ops_byname("epoll");
+
+ glue->poll_ops = tevent_find_ops_byname("poll");
+ if (glue->poll_ops == NULL) {
+ return -1;
+ }
+
+ /*
+ * Allocate space for our custom ops.
+ * Allocate as a child of our epoll_ops pointer
+ * so we can easily get to it using talloc_parent.
+ */
+ glue->glue_ops = talloc_zero(glue, struct tevent_ops);
+ if (glue->glue_ops == NULL) {
+ talloc_free(glue);
+ return -1;
+ }
+
+ ev->ops = glue->glue_ops;
+ } else {
+ void *glue_ptr = talloc_parent(ev->ops);
+ glue = talloc_get_type_abort(glue_ptr, struct std_event_glue);
+ }
+
+ if (glue->epoll_ops != NULL) {
+ /*
+ * Set custom_ops the same as epoll,
+ * except re-init using std_event_context_init()
+ * and use std_event_loop_once() to add the
+ * ability to fallback to a poll backend on
+ * epoll runtime error.
+ */
+ *glue->glue_ops = *glue->epoll_ops;
+ glue->glue_ops->context_init = std_event_context_init;
+ glue->glue_ops->loop_once = std_event_loop_once;
+
+ ret = glue->epoll_ops->context_init(ev);
+ if (ret == -1) {
+ goto fallback;
+ }
+#ifdef HAVE_EPOLL
+ if (!tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll)) {
+ TALLOC_FREE(ev->additional_data);
+ goto fallback;
+ }
+#endif
+
+ return ret;
+ }
+
+fallback:
+ glue->epoll_ops = NULL;
+
+ /*
+ * Set custom_ops the same as poll.
+ */
+ *glue->glue_ops = *glue->poll_ops;
+ glue->glue_ops->context_init = std_event_context_init;
+
+ return glue->poll_ops->context_init(ev);
+}
_PRIVATE_ bool tevent_standard_init(void)
{
return tevent_register_backend("standard", &std_event_ops);
}
-
--
1.7.9.5
From 27e0a9a470a8cd8fdf11a7541f40056a364d1080 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 11 Feb 2013 11:42:08 -0800
Subject: [PATCH 13/17] tevent: Remove the previous "standard" tevent backend
implementation.
This was a horrible hybrid of duplicated epoll and select()
code.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
lib/tevent/tevent_standard.c | 557 +-----------------------------------------
1 file changed, 1 insertion(+), 556 deletions(-)
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index 0c72226..d7a5bd7 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -1,8 +1,7 @@
/*
Unix SMB/CIFS implementation.
main select loop and event handling
- Copyright (C) Andrew Tridgell 2003-2005
- Copyright (C) Stefan Metzmacher 2005-2013
+ Copyright (C) Stefan Metzmacher 2013
Copyright (C) Jeremy Allison 2013
** NOTE! The following LGPL license applies to the tevent
@@ -37,560 +36,6 @@
#include "tevent_util.h"
#include "tevent_internal.h"
-#if 0
-struct std_event_context {
- /* a pointer back to the generic event_context */
- struct tevent_context *ev;
-
- /* the maximum file descriptor number in fd_events */
- int maxfd;
-
- /* information for exiting from the event loop */
- int exit_code;
-
- /* when using epoll this is the handle from epoll_create */
- int epoll_fd;
-
- /* our pid at the time the epoll_fd was created */
- pid_t pid;
-};
-
-/* use epoll if it is available */
-#if HAVE_EPOLL
-/*
- called when a epoll call fails, and we should fallback
- to using select
-*/
-static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
-{
- tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
- "%s (%s) - falling back to select()\n",
- reason, strerror(errno));
- close(std_ev->epoll_fd);
- std_ev->epoll_fd = -1;
- talloc_set_destructor(std_ev, NULL);
-}
-
-/*
- map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
-*/
-static uint32_t epoll_map_flags(uint16_t flags)
-{
- uint32_t ret = 0;
- if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
- if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
- return ret;
-}
-
-/*
- free the epoll fd
-*/
-static int epoll_ctx_destructor(struct std_event_context *std_ev)
-{
- if (std_ev->epoll_fd != -1) {
- close(std_ev->epoll_fd);
- }
- std_ev->epoll_fd = -1;
- return 0;
-}
-
-/*
- init the epoll fd
-*/
-static void epoll_init_ctx(struct std_event_context *std_ev)
-{
- std_ev->epoll_fd = epoll_create(64);
- if (std_ev->epoll_fd == -1) {
- tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
- "Failed to create epoll handle.\n");
- return;
- }
-
- if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
- tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
- "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
- }
-
- std_ev->pid = getpid();
- talloc_set_destructor(std_ev, epoll_ctx_destructor);
-}
-
-static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
-
-/*
- reopen the epoll handle when our pid changes
- see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
- demonstration of why this is needed
- */
-static void epoll_check_reopen(struct std_event_context *std_ev)
-{
- struct tevent_fd *fde;
-
- if (std_ev->pid == getpid()) {
- return;
- }
-
- close(std_ev->epoll_fd);
- std_ev->epoll_fd = epoll_create(64);
- if (std_ev->epoll_fd == -1) {
- tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
- "Failed to recreate epoll handle after fork\n");
- return;
- }
-
- if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
- tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
- "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
- }
-
- std_ev->pid = getpid();
- for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
- epoll_add_event(std_ev, fde);
- }
-}
-
-#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
-#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
-#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
-
-/*
- add the epoll event to the given fd_event
-*/
-static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
-{
- struct epoll_event event;
- if (std_ev->epoll_fd == -1) return;
-
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
-
- /* if we don't want events yet, don't add an epoll_event */
- if (fde->flags == 0) return;
-
- ZERO_STRUCT(event);
- event.events = epoll_map_flags(fde->flags);
- event.data.ptr = fde;
- if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
- epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
- }
- fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
-
- /* only if we want to read we want to tell the event handler about errors */
- if (fde->flags & TEVENT_FD_READ) {
- fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
- }
-}
-
-/*
- delete the epoll event for given fd_event
-*/
-static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
-{
- struct epoll_event event;
- if (std_ev->epoll_fd == -1) return;
-
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
-
- /* if there's no epoll_event, we don't need to delete it */
- if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
-
- ZERO_STRUCT(event);
- event.events = epoll_map_flags(fde->flags);
- event.data.ptr = fde;
- epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
-}
-
-/*
- change the epoll event to the given fd_event
-*/
-static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
-{
- struct epoll_event event;
- if (std_ev->epoll_fd == -1) return;
-
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
-
- ZERO_STRUCT(event);
- event.events = epoll_map_flags(fde->flags);
- event.data.ptr = fde;
- if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
- epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
- }
-
- /* only if we want to read we want to tell the event handler about errors */
- if (fde->flags & TEVENT_FD_READ) {
- fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
- }
-}
-
-static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
-{
- bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
- bool want_read = (fde->flags & TEVENT_FD_READ);
- bool want_write= (fde->flags & TEVENT_FD_WRITE);
-
- if (std_ev->epoll_fd == -1) return;
-
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
-
- /* there's already an event */
- if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
- if (want_read || (want_write && !got_error)) {
- epoll_mod_event(std_ev, fde);
- return;
- }
- /*
- * if we want to match the select behavior, we need to remove the epoll_event
- * when the caller isn't interested in events.
- *
- * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
- */
- epoll_del_event(std_ev, fde);
- return;
- }
-
- /* there's no epoll_event attached to the fde */
- if (want_read || (want_write && !got_error)) {
- epoll_add_event(std_ev, fde);
- return;
- }
-}
-
-/*
- event loop handling using epoll
-*/
-static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
-{
- int ret, i;
-#define MAXEVENTS 1
- struct epoll_event events[MAXEVENTS];
- int timeout = -1;
-
- if (std_ev->epoll_fd == -1) return -1;
-
- if (tvalp) {
- /* it's better to trigger timed events a bit later than to early */
- timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
- }
-
- if (std_ev->ev->signal_events &&
- tevent_common_check_signal(std_ev->ev)) {
- return 0;
- }
-
- tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
- ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
- tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_AFTER_WAIT);
-
- if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
- if (tevent_common_check_signal(std_ev->ev)) {
- return 0;
- }
- }
-
- if (ret == -1 && errno != EINTR) {
- epoll_fallback_to_select(std_ev, "epoll_wait() failed");
- return -1;
- }
-
- if (ret == 0 && tvalp) {
- /* we don't care about a possible delay here */
- tevent_common_loop_timer_delay(std_ev->ev);
- return 0;
- }
-
- for (i=0;i<ret;i++) {
- struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
- struct tevent_fd);
- uint16_t flags = 0;
-
- if (fde == NULL) {
- epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
- return -1;
- }
- if (events[i].events & (EPOLLHUP|EPOLLERR)) {
- fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
- /*
- * if we only wait for TEVENT_FD_WRITE, we should not tell the
- * event handler about it, and remove the epoll_event,
- * as we only report errors when waiting for read events,
- * to match the select() behavior
- */
- if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
- epoll_del_event(std_ev, fde);
- continue;
- }
- flags |= TEVENT_FD_READ;
- }
- if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
- if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
- if (flags) {
- fde->handler(std_ev->ev, fde, flags, fde->private_data);
- break;
- }
- }
-
- return 0;
-}
-#else
-#define epoll_init_ctx(std_ev)
-#define epoll_add_event(std_ev,fde)
-#define epoll_del_event(std_ev,fde)
-#define epoll_change_event(std_ev,fde)
-#define epoll_event_loop(std_ev,tvalp) (-1)
-#define epoll_check_reopen(std_ev)
-#endif
-
-/*
- create a std_event_context structure.
-*/
-static int std_event_context_init(struct tevent_context *ev)
-{
- struct std_event_context *std_ev;
-
- /*
- * We might be called during tevent_re_initialise()
- * which means we need to free our old additional_data.
- */
- TALLOC_FREE(ev->additional_data);
-
- std_ev = talloc_zero(ev, struct std_event_context);
- if (!std_ev) return -1;
- std_ev->ev = ev;
- std_ev->epoll_fd = -1;
-
- epoll_init_ctx(std_ev);
-
- ev->additional_data = std_ev;
- return 0;
-}
-
-/*
- recalculate the maxfd
-*/
-static void calc_maxfd(struct std_event_context *std_ev)
-{
- struct tevent_fd *fde;
-
- std_ev->maxfd = 0;
- for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
- if (fde->fd > std_ev->maxfd) {
- std_ev->maxfd = fde->fd;
- }
- }
-}
-
-
-/* to mark the ev->maxfd invalid
- * this means we need to recalculate it
- */
-#define EVENT_INVALID_MAXFD (-1)
-
-/*
- destroy an fd_event
-*/
-static int std_event_fd_destructor(struct tevent_fd *fde)
-{
- struct tevent_context *ev = fde->event_ctx;
- struct std_event_context *std_ev = NULL;
-
- if (ev) {
- std_ev = talloc_get_type(ev->additional_data,
- struct std_event_context);
-
- epoll_check_reopen(std_ev);
-
- if (std_ev->maxfd == fde->fd) {
- std_ev->maxfd = EVENT_INVALID_MAXFD;
- }
-
- epoll_del_event(std_ev, fde);
- }
-
- return tevent_common_fd_destructor(fde);
-}
-
-/*
- add a fd based event
- return NULL on failure (memory allocation error)
-*/
-static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
- int fd, uint16_t flags,
- tevent_fd_handler_t handler,
- void *private_data,
- const char *handler_name,
- const char *location)
-{
- struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
- struct std_event_context);
- struct tevent_fd *fde;
-
- epoll_check_reopen(std_ev);
-
- fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
- handler, private_data,
- handler_name, location);
- if (!fde) return NULL;
-
- if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
- && (fde->fd > std_ev->maxfd)) {
- std_ev->maxfd = fde->fd;
- }
- talloc_set_destructor(fde, std_event_fd_destructor);
-
- epoll_add_event(std_ev, fde);
-
- return fde;
-}
-
-/*
- set the fd event flags
-*/
-static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
-{
- struct tevent_context *ev;
- struct std_event_context *std_ev;
-
- if (fde->flags == flags) return;
-
- ev = fde->event_ctx;
- std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
-
- fde->flags = flags;
-
- epoll_check_reopen(std_ev);
-
- epoll_change_event(std_ev, fde);
-}
-
-/*
- event loop handling using select()
-*/
-static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
-{
- fd_set r_fds, w_fds;
- struct tevent_fd *fde;
- int selrtn;
-
- /* we maybe need to recalculate the maxfd */
- if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
- calc_maxfd(std_ev);
- }
-
- FD_ZERO(&r_fds);
- FD_ZERO(&w_fds);
-
- /* setup any fd events */
- for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
- if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
- std_ev->exit_code = EBADF;
- return -1;
- }
- if (fde->flags & TEVENT_FD_READ) {
- FD_SET(fde->fd, &r_fds);
- }
- if (fde->flags & TEVENT_FD_WRITE) {
- FD_SET(fde->fd, &w_fds);
- }
- }
-
- if (std_ev->ev->signal_events &&
- tevent_common_check_signal(std_ev->ev)) {
- return 0;
- }
-
- selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
-
- if (selrtn == -1 && errno == EINTR &&
- std_ev->ev->signal_events) {
- tevent_common_check_signal(std_ev->ev);
- return 0;
- }
-
- if (selrtn == -1 && errno == EBADF) {
- /* the socket is dead! this should never
- happen as the socket should have first been
- made readable and that should have removed
- the event, so this must be a bug. This is a
- fatal error. */
- tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
- "ERROR: EBADF on std_event_loop_once\n");
- std_ev->exit_code = EBADF;
- return -1;
- }
-
- if (selrtn == 0 && tvalp) {
- /* we don't care about a possible delay here */
- tevent_common_loop_timer_delay(std_ev->ev);
- return 0;
- }
-
- if (selrtn > 0) {
- /* at least one file descriptor is ready - check
- which ones and call the handler, being careful to allow
- the handler to remove itself when called */
- for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
- uint16_t flags = 0;
-
- if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
- if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
- if (flags & fde->flags) {
- fde->handler(std_ev->ev, fde, flags, fde->private_data);
- break;
- }
- }
- }
-
- return 0;
-}
-
-/*
- do a single event loop using the events defined in ev
-*/
-static int std_event_loop_once(struct tevent_context *ev, const char *location)
-{
- struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
- struct std_event_context);
- struct timeval tval;
-
- if (ev->signal_events &&
- tevent_common_check_signal(ev)) {
- return 0;
- }
-
- if (ev->immediate_events &&
- tevent_common_loop_immediate(ev)) {
- return 0;
- }
-
- tval = tevent_common_loop_timer_delay(ev);
- if (tevent_timeval_is_zero(&tval)) {
- return 0;
- }
-
- epoll_check_reopen(std_ev);
-
- if (epoll_event_loop(std_ev, &tval) == 0) {
- return 0;
- }
-
- return std_event_loop_select(std_ev, &tval);
-}
-
-static const struct tevent_ops std_event_ops = {
- .context_init = std_event_context_init,
- .add_fd = std_event_add_fd,
- .set_fd_close_fn = tevent_common_fd_set_close_fn,
- .get_fd_flags = tevent_common_fd_get_flags,
- .set_fd_flags = std_event_set_fd_flags,
- .add_timer = tevent_common_add_timer,
- .schedule_immediate = tevent_common_schedule_immediate,
- .add_signal = tevent_common_add_signal,
- .loop_once = std_event_loop_once,
- .loop_wait = tevent_common_loop_wait,
-};
-#endif
-
struct std_event_glue {
const struct tevent_ops *epoll_ops;
const struct tevent_ops *poll_ops;
--
1.7.9.5
From 9995e3fc9e9ee6cb91563e5ec2d21bd944f191e2 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 15:46:18 +0100
Subject: [PATCH 14/17] HACK tevent fallback testing
TDB_NO_FSYNC=1 buildnice make -j test TESTS=LOCAL-WBCLIENT
---
lib/tevent/tevent_epoll.c | 16 ++++++++++++++++
lib/tevent/tevent_poll.c | 2 ++
source3/torture/torture.c | 19 ++++++++++++++++++-
3 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 8696215..81949d4 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -43,7 +43,9 @@ struct epoll_event_context {
bool (*panic_fallback)(struct tevent_context *ev, bool replay);
};
+#define TEST_PANIC_FALLBACK
#ifdef TEST_PANIC_FALLBACK
+
static int epoll_wait_panic_fallback(int epfd,
struct epoll_event *events,
int maxevents,
@@ -58,7 +60,19 @@ static int epoll_wait_panic_fallback(int epfd,
return epoll_wait(epfd, events, maxevents, timeout);
}
+static int epoll_ctl_panic_fallback(int epfd, int op, int fd, struct epoll_event *event)
+{
+ /* 50% of the time, fail... */
+ if ((random() % 2) == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return epoll_ctl(epfd, op, fd, event);
+}
+
#define epoll_wait epoll_wait_panic_fallback
+#define epoll_ctl epoll_ctl_panic_fallback
#endif
/*
@@ -488,6 +502,8 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
struct epoll_event_context);
struct timeval tval;
+ tevent_debug(ev, TEVENT_DEBUG_WARNING,
+ "%s:%s\n", __location__, __FUNCTION__);
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
return 0;
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 89b3bbc..8c5f834 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -545,6 +545,8 @@ static int poll_event_loop_once(struct tevent_context *ev,
{
struct timeval tval;
+ tevent_debug(ev, TEVENT_DEBUG_WARNING,
+ "%s:%s\n", __location__, __FUNCTION__);
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
return 0;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index b59ac30..d93a23c 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -8516,6 +8516,22 @@ static void wbclient_done(struct tevent_req *req)
d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
}
+/*
+ this is used to catch debug messages from events
+*/
+static void s3t_event_debug(void *context, enum tevent_debug_level level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+
+static void s3t_event_debug(void *context, enum tevent_debug_level level,
+ const char *fmt, va_list ap)
+{
+ char *s = NULL;
+ if (vasprintf(&s, fmt, ap) == -1) {
+ return;
+ }
+ d_printf("s3t_event: %s", s);
+ free(s);
+}
static bool run_local_wbclient(int dummy)
{
struct event_context *ev;
@@ -8526,10 +8542,11 @@ static bool run_local_wbclient(int dummy)
BlockSignals(True, SIGPIPE);
- ev = tevent_context_init_byname(talloc_tos(), "epoll");
+ ev = tevent_context_init_byname(talloc_tos(), "standard");
if (ev == NULL) {
goto fail;
}
+ tevent_set_debug(ev, s3t_event_debug, NULL);
wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
if (wb_ctx == NULL) {
--
1.7.9.5
From 2e42cad9195a2c8bc4dddc64dd2032a0c3b08ecc Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 15:52:46 +0100
Subject: [PATCH 15/17] HACK blackbox subunit print ok
TDB_NO_FSYNC=1 buildnice make -j test TESTS=LOCAL-WBCLIENT
...
less st/subunit
---
testprogs/blackbox/subunit.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/testprogs/blackbox/subunit.sh b/testprogs/blackbox/subunit.sh
index 9b047a2..03e6e51 100755
--- a/testprogs/blackbox/subunit.sh
+++ b/testprogs/blackbox/subunit.sh
@@ -62,6 +62,7 @@ testit () {
output=`$cmdline 2>&1`
status=$?
if [ x$status = x0 ]; then
+ echo "$output"
subunit_pass_test "$name"
else
echo "$output" | subunit_fail_test "$name"
--
1.7.9.5
From 42c6997e26f129ff98087402d1cdab789a32c7a4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 15:59:11 +0100
Subject: [PATCH 16/17] Revert "HACK blackbox subunit print ok"
This reverts commit 2e42cad9195a2c8bc4dddc64dd2032a0c3b08ecc.
---
testprogs/blackbox/subunit.sh | 1 -
1 file changed, 1 deletion(-)
diff --git a/testprogs/blackbox/subunit.sh b/testprogs/blackbox/subunit.sh
index 03e6e51..9b047a2 100755
--- a/testprogs/blackbox/subunit.sh
+++ b/testprogs/blackbox/subunit.sh
@@ -62,7 +62,6 @@ testit () {
output=`$cmdline 2>&1`
status=$?
if [ x$status = x0 ]; then
- echo "$output"
subunit_pass_test "$name"
else
echo "$output" | subunit_fail_test "$name"
--
1.7.9.5
From f722eb01ba5eb611fb99208a6188c9a8bc675e99 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 14 Feb 2013 15:59:18 +0100
Subject: [PATCH 17/17] Revert "HACK tevent fallback testing"
This reverts commit 9995e3fc9e9ee6cb91563e5ec2d21bd944f191e2.
---
lib/tevent/tevent_epoll.c | 16 ----------------
lib/tevent/tevent_poll.c | 2 --
source3/torture/torture.c | 19 +------------------
3 files changed, 1 insertion(+), 36 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 81949d4..8696215 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -43,9 +43,7 @@ struct epoll_event_context {
bool (*panic_fallback)(struct tevent_context *ev, bool replay);
};
-#define TEST_PANIC_FALLBACK
#ifdef TEST_PANIC_FALLBACK
-
static int epoll_wait_panic_fallback(int epfd,
struct epoll_event *events,
int maxevents,
@@ -60,19 +58,7 @@ static int epoll_wait_panic_fallback(int epfd,
return epoll_wait(epfd, events, maxevents, timeout);
}
-static int epoll_ctl_panic_fallback(int epfd, int op, int fd, struct epoll_event *event)
-{
- /* 50% of the time, fail... */
- if ((random() % 2) == 0) {
- errno = EINVAL;
- return -1;
- }
-
- return epoll_ctl(epfd, op, fd, event);
-}
-
#define epoll_wait epoll_wait_panic_fallback
-#define epoll_ctl epoll_ctl_panic_fallback
#endif
/*
@@ -502,8 +488,6 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
struct epoll_event_context);
struct timeval tval;
- tevent_debug(ev, TEVENT_DEBUG_WARNING,
- "%s:%s\n", __location__, __FUNCTION__);
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
return 0;
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 8c5f834..89b3bbc 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -545,8 +545,6 @@ static int poll_event_loop_once(struct tevent_context *ev,
{
struct timeval tval;
- tevent_debug(ev, TEVENT_DEBUG_WARNING,
- "%s:%s\n", __location__, __FUNCTION__);
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
return 0;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index d93a23c..b59ac30 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -8516,22 +8516,6 @@ static void wbclient_done(struct tevent_req *req)
d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
}
-/*
- this is used to catch debug messages from events
-*/
-static void s3t_event_debug(void *context, enum tevent_debug_level level,
- const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
-
-static void s3t_event_debug(void *context, enum tevent_debug_level level,
- const char *fmt, va_list ap)
-{
- char *s = NULL;
- if (vasprintf(&s, fmt, ap) == -1) {
- return;
- }
- d_printf("s3t_event: %s", s);
- free(s);
-}
static bool run_local_wbclient(int dummy)
{
struct event_context *ev;
@@ -8542,11 +8526,10 @@ static bool run_local_wbclient(int dummy)
BlockSignals(True, SIGPIPE);
- ev = tevent_context_init_byname(talloc_tos(), "standard");
+ ev = tevent_context_init_byname(talloc_tos(), "epoll");
if (ev == NULL) {
goto fail;
}
- tevent_set_debug(ev, s3t_event_debug, NULL);
wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
if (wb_ctx == NULL) {
--
1.7.9.5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 261 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20130214/0ab70a2d/attachment-0001.pgp>
More information about the samba-technical
mailing list