[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Thu Aug 16 14:50:03 MDT 2012
The branch, master has been updated
via f3b69da s3-libsmb: Add a simple test for python bindings
via fbebd75 s3-libsmb: Add a python wrapper
via d7d8646 tevent: change version to 0.9.17 after adding the "poll_mt" backend
via d7af2c8 tevent: Add threaded poll_mt testcase
via fa71f32 lib/tevent: Add a thread-safe tevent backend
via d860aa2 tevent_poll: Decouple poll_ev->fds handling from adding/removing fds
from cbe2510 s3-g_lock: Make g_lock_lock more robust
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit f3b69da2aeb637398b0670cfb4a29379a8000d91
Author: Volker Lendecke <vl at samba.org>
Date: Wed Aug 15 14:08:45 2012 +0200
s3-libsmb: Add a simple test for python bindings
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
Autobuild-Date(master): Thu Aug 16 22:49:06 CEST 2012 on sn-devel-104
commit fbebd7530ed365ac6a7c7ae004975850b4f4d162
Author: Volker Lendecke <vl at samba.org>
Date: Thu Aug 2 23:21:27 2012 +0200
s3-libsmb: Add a python wrapper
Please note that this is not finished and only for internal use.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit d7d8646e6352c3e28012e52bd926283b1d1a09c9
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 16 21:06:45 2012 +0200
tevent: change version to 0.9.17 after adding the "poll_mt" backend
metze
commit d7af2c842a5db2a1dd9f61b463ccfee24d7db5ed
Author: Volker Lendecke <vl at samba.org>
Date: Mon Jul 30 09:09:46 2012 +0200
tevent: Add threaded poll_mt testcase
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit fa71f3241110fbe079de6d6cb0c8f3df001f4c65
Author: Volker Lendecke <vl at samba.org>
Date: Mon Aug 13 16:06:01 2012 +0200
lib/tevent: Add a thread-safe tevent backend
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit d860aa2cacc783434973c14f7ae21964ca050e6f
Author: Volker Lendecke <vl at samba.org>
Date: Sun Jul 29 13:05:36 2012 +0200
tevent_poll: Decouple poll_ev->fds handling from adding/removing fds
Step 1 in a python backend for multiple threads
Signed-off-by: Stefan Metzmacher <metze at samba.org>
-----------------------------------------------------------------------
Summary of changes:
.../ABI/{tevent-0.9.16.sigs => tevent-0.9.17.sigs} | 0
lib/tevent/testsuite.c | 145 +++++
lib/tevent/tevent.c | 1 +
lib/tevent/tevent_internal.h | 1 +
lib/tevent/tevent_poll.c | 364 +++++++++---
lib/tevent/wscript | 2 +-
source3/libsmb/pylibsmb.c | 671 ++++++++++++++++++++
source3/smbd/pysmbd.c | 2 +-
source3/wscript_build | 6 +
.../python/samba/tests/libsmb_samba_internal.py | 78 +++
source4/selftest/tests.py | 2 +
11 files changed, 1197 insertions(+), 75 deletions(-)
copy lib/tevent/ABI/{tevent-0.9.16.sigs => tevent-0.9.17.sigs} (100%)
create mode 100644 source3/libsmb/pylibsmb.c
create mode 100644 source4/scripting/python/samba/tests/libsmb_samba_internal.py
Changeset truncated at 500 lines:
diff --git a/lib/tevent/ABI/tevent-0.9.16.sigs b/lib/tevent/ABI/tevent-0.9.17.sigs
similarity index 100%
copy from lib/tevent/ABI/tevent-0.9.16.sigs
copy to lib/tevent/ABI/tevent-0.9.17.sigs
diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c
index 5868f0a..3d2a79a 100644
--- a/lib/tevent/testsuite.c
+++ b/lib/tevent/testsuite.c
@@ -26,7 +26,12 @@
#include "includes.h"
#include "lib/tevent/tevent.h"
#include "system/filesys.h"
+#include "system/select.h"
#include "torture/torture.h"
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#include <assert.h>
+#endif
static int fde_count;
@@ -146,6 +151,140 @@ static bool test_event_context(struct torture_context *test,
return true;
}
+#ifdef HAVE_PTHREAD
+
+static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool do_shutdown = false;
+
+static void test_event_threaded_lock(void)
+{
+ int ret;
+ ret = pthread_mutex_lock(&threaded_mutex);
+ assert(ret == 0);
+}
+
+static void test_event_threaded_unlock(void)
+{
+ int ret;
+ ret = pthread_mutex_unlock(&threaded_mutex);
+ assert(ret == 0);
+}
+
+static void test_event_threaded_trace(enum tevent_trace_point point,
+ void *private_data)
+{
+ switch (point) {
+ case TEVENT_TRACE_BEFORE_WAIT:
+ test_event_threaded_unlock();
+ break;
+ case TEVENT_TRACE_AFTER_WAIT:
+ test_event_threaded_lock();
+ break;
+ }
+}
+
+static void test_event_threaded_timer(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval current_time,
+ void *private_data)
+{
+ return;
+}
+
+static void *test_event_poll_thread(void *private_data)
+{
+ struct tevent_context *ev = (struct tevent_context *)private_data;
+
+ test_event_threaded_lock();
+
+ while (true) {
+ int ret;
+ ret = tevent_loop_once(ev);
+ assert(ret == 0);
+ if (do_shutdown) {
+ test_event_threaded_unlock();
+ return NULL;
+ }
+ }
+
+}
+
+static void test_event_threaded_read_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags,
+ void *private_data)
+{
+ int *pfd = (int *)private_data;
+ char c;
+ ssize_t nread;
+
+ if ((flags & TEVENT_FD_READ) == 0) {
+ return;
+ }
+
+ do {
+ nread = read(*pfd, &c, 1);
+ } while ((nread == -1) && (errno == EINTR));
+
+ assert(nread == 1);
+}
+
+static bool test_event_context_threaded(struct torture_context *test,
+ const void *test_data)
+{
+ struct tevent_context *ev;
+ struct tevent_timer *te;
+ struct tevent_fd *fde;
+ pthread_t poll_thread;
+ int fds[2];
+ int ret;
+ char c = 0;
+
+ ev = tevent_context_init_byname(test, "poll_mt");
+ torture_assert(test, ev != NULL, "poll_mt not supported");
+
+ tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
+
+ te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
+ test_event_threaded_timer, NULL);
+ torture_assert(test, te != NULL, "Could not add timer");
+
+ ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
+ torture_assert(test, ret == 0, "Could not create poll thread");
+
+ ret = pipe(fds);
+ torture_assert(test, ret == 0, "Could not create pipe");
+
+ poll(NULL, 0, 100);
+
+ test_event_threaded_lock();
+
+ fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
+ test_event_threaded_read_handler, &fds[0]);
+ torture_assert(test, fde != NULL, "Could not add fd event");
+
+ test_event_threaded_unlock();
+
+ poll(NULL, 0, 100);
+
+ write(fds[1], &c, 1);
+
+ poll(NULL, 0, 100);
+
+ test_event_threaded_lock();
+ do_shutdown = true;
+ test_event_threaded_unlock();
+
+ write(fds[1], &c, 1);
+
+ ret = pthread_join(poll_thread, NULL);
+ torture_assert(test, ret == 0, "pthread_join failed");
+
+ return true;
+}
+
+#endif
+
struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
{
struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
@@ -158,5 +297,11 @@ struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
(const void *)list[i]);
}
+#ifdef HAVE_PTHREAD
+ torture_suite_add_simple_tcase_const(suite, "poll_mt_threaded",
+ test_event_context_threaded,
+ NULL);
+#endif
+
return suite;
}
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index 61ffc7e..fa842e4 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -114,6 +114,7 @@ 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();
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index 877510f..f09cf57 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -315,6 +315,7 @@ 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);
+bool tevent_poll_mt_init(void);
#ifdef HAVE_EPOLL
bool tevent_epoll_init(void);
#endif
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 7ae3c42..da8cc01 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -34,11 +34,22 @@ struct poll_event_context {
struct tevent_context *ev;
/*
+ * A DLIST for fresh fde's added by poll_event_add_fd but not
+ * picked up yet by poll_event_loop_once
+ */
+ struct tevent_fd *fresh;
+
+ /*
* These two arrays are maintained together.
*/
struct pollfd *fds;
- struct tevent_fd **fd_events;
- uint64_t num_fds;
+ struct tevent_fd **fdes;
+ unsigned num_fds;
+
+ /*
+ * Signal fd to wake the poll() thread
+ */
+ int signal_fd;
/* information for exiting from the event loop */
int exit_code;
@@ -56,18 +67,125 @@ static int poll_event_context_init(struct tevent_context *ev)
return -1;
}
poll_ev->ev = ev;
+ poll_ev->signal_fd = -1;
ev->additional_data = poll_ev;
return 0;
}
+static int poll_event_mt_destructor(struct poll_event_context *poll_ev)
+{
+ if (poll_ev->signal_fd != -1) {
+ close(poll_ev->signal_fd);
+ poll_ev->signal_fd = -1;
+ }
+ if (poll_ev->num_fds == 0) {
+ return 0;
+ }
+ if (poll_ev->fds[0].fd != -1) {
+ close(poll_ev->fds[0].fd);
+ poll_ev->fds[0].fd = -1;
+ }
+ return 0;
+}
+
+static bool set_nonblock(int fd)
+{
+ int val;
+
+ val = fcntl(fd, F_GETFL, 0);
+ if (val == -1) {
+ return false;
+ }
+ val |= O_NONBLOCK;
+
+ return (fcntl(fd, F_SETFL, val) != -1);
+}
+
+static int poll_event_context_init_mt(struct tevent_context *ev)
+{
+ struct poll_event_context *poll_ev;
+ struct pollfd *pfd;
+ int fds[2];
+ int ret;
+
+ ret = poll_event_context_init(ev);
+ if (ret == -1) {
+ return ret;
+ }
+
+ poll_ev = talloc_get_type_abort(
+ ev->additional_data, struct poll_event_context);
+
+ poll_ev->fds = talloc_zero(poll_ev, struct pollfd);
+ if (poll_ev->fds == NULL) {
+ return -1;
+ }
+
+ ret = pipe(fds);
+ if (ret == -1) {
+ return -1;
+ }
+
+ if (!set_nonblock(fds[0]) || !set_nonblock(fds[1])) {
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+
+ poll_ev->signal_fd = fds[1];
+
+ pfd = &poll_ev->fds[0];
+ pfd->fd = fds[0];
+ pfd->events = (POLLIN|POLLHUP);
+
+ poll_ev->num_fds = 1;
+
+ talloc_set_destructor(poll_ev, poll_event_mt_destructor);
+
+ return 0;
+}
+
+static void poll_event_wake_pollthread(struct poll_event_context *poll_ev)
+{
+ char c;
+ ssize_t ret;
+
+ if (poll_ev->signal_fd == -1) {
+ return;
+ }
+ c = 0;
+ do {
+ ret = write(poll_ev->signal_fd, &c, sizeof(c));
+ } while ((ret == -1) && (errno == EINTR));
+}
+
+static void poll_event_drain_signal_fd(struct poll_event_context *poll_ev)
+{
+ char buf[16];
+ ssize_t ret;
+ int fd;
+
+ if (poll_ev->signal_fd == -1) {
+ return;
+ }
+
+ if (poll_ev->num_fds < 1) {
+ return;
+ }
+ fd = poll_ev->fds[0].fd;
+
+ do {
+ ret = read(fd, buf, sizeof(buf));
+ } while (ret == sizeof(buf));
+}
+
/*
destroy an fd_event
*/
static int poll_event_fd_destructor(struct tevent_fd *fde)
{
struct tevent_context *ev = fde->event_ctx;
- struct poll_event_context *poll_ev = NULL;
- struct tevent_fd *moved_fde;
+ struct poll_event_context *poll_ev;
uint64_t del_idx = fde->additional_flags;
if (ev == NULL) {
@@ -77,16 +195,35 @@ static int poll_event_fd_destructor(struct tevent_fd *fde)
poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
- moved_fde = poll_ev->fd_events[poll_ev->num_fds-1];
- poll_ev->fd_events[del_idx] = moved_fde;
- poll_ev->fds[del_idx] = poll_ev->fds[poll_ev->num_fds-1];
- moved_fde->additional_flags = del_idx;
-
- poll_ev->num_fds -= 1;
+ poll_ev->fdes[del_idx] = NULL;
+ poll_event_wake_pollthread(poll_ev);
done:
return tevent_common_fd_destructor(fde);
}
+static int poll_fresh_fde_destructor(struct tevent_fd *fde)
+{
+ struct poll_event_context *poll_ev = talloc_get_type_abort(
+ fde->event_ctx->additional_data, struct poll_event_context);
+ DLIST_REMOVE(poll_ev->fresh, fde);
+ return 0;
+}
+
+static void poll_event_schedule_immediate(struct tevent_immediate *im,
+ struct tevent_context *ev,
+ tevent_immediate_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location)
+{
+ struct poll_event_context *poll_ev = talloc_get_type_abort(
+ ev->additional_data, struct poll_event_context);
+
+ tevent_common_schedule_immediate(im, ev, handler, private_data,
+ handler_name, location);
+ poll_event_wake_pollthread(poll_ev);
+}
+
/*
add a fd based event
return NULL on failure (memory allocation error)
@@ -101,60 +238,35 @@ static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev,
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
- struct pollfd *pfd;
struct tevent_fd *fde;
- fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
- handler, private_data,
- handler_name, location);
- if (fde == NULL) {
+ if (fd < 0) {
return NULL;
}
- /* we allocate 16 slots to avoid a lot of reallocations */
- if (talloc_array_length(poll_ev->fds) == poll_ev->num_fds) {
- struct pollfd *tmp_fds;
- struct tevent_fd **tmp_fd_events;
- tmp_fds = talloc_realloc(
- poll_ev, poll_ev->fds, struct pollfd,
- poll_ev->num_fds + 16);
- if (tmp_fds == NULL) {
- TALLOC_FREE(fde);
- return NULL;
- }
- poll_ev->fds = tmp_fds;
-
- tmp_fd_events = talloc_realloc(
- poll_ev, poll_ev->fd_events, struct tevent_fd *,
- poll_ev->num_fds + 16);
- if (tmp_fd_events == NULL) {
- TALLOC_FREE(fde);
- return NULL;
- }
- poll_ev->fd_events = tmp_fd_events;
- }
-
- pfd = &poll_ev->fds[poll_ev->num_fds];
-
- pfd->fd = fd;
-
- pfd->events = 0;
- pfd->revents = 0;
-
- if (flags & TEVENT_FD_READ) {
- pfd->events |= (POLLIN|POLLHUP);
- }
- if (flags & TEVENT_FD_WRITE) {
- pfd->events |= (POLLOUT);
+ fde = talloc(mem_ctx ? mem_ctx : ev, struct tevent_fd);
+ if (fde == NULL) {
+ return NULL;
}
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->close_fn = NULL;
+ fde->private_data = private_data;
+ fde->handler_name = handler_name;
+ fde->location = location;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ DLIST_ADD(poll_ev->fresh, fde);
+ talloc_set_destructor(fde, poll_fresh_fde_destructor);
+ poll_event_wake_pollthread(poll_ev);
- fde->additional_flags = poll_ev->num_fds;
- poll_ev->fd_events[poll_ev->num_fds] = fde;
-
- poll_ev->num_fds += 1;
-
- talloc_set_destructor(fde, poll_event_fd_destructor);
-
+ /*
+ * poll_event_loop_poll will take care of the rest in
+ * poll_event_setup_fresh
+ */
return fde;
}
@@ -178,6 +290,82 @@ static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
poll_ev->fds[idx].events = pollflags;
fde->flags = flags;
+ poll_event_wake_pollthread(poll_ev);
+}
+
+static bool poll_event_setup_fresh(struct tevent_context *ev,
+ struct poll_event_context *poll_ev)
+{
+ struct tevent_fd *fde, *next;
+ unsigned num_fresh, num_fds;
+
+ if (poll_ev->fresh == NULL) {
+ return true;
+ }
+
+ num_fresh = 0;
+ for (fde = poll_ev->fresh; fde; fde = fde->next) {
+ num_fresh += 1;
--
Samba Shared Repository
More information about the samba-cvs
mailing list