From 26c8619a557f91371864ccd214ce2ec84cdc9f33 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Mar 2015 21:15:53 +0200 Subject: [PATCH 01/14] tevent: Fix CID 1035381 Unchecked return value Signed-off-by: Volker Lendecke Reviewed-by: Michael Adam (cherry picked from commit 6bcc037b5b636e88a914f1d39a95eb6eb72937e0) --- lib/tevent/testsuite.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index 34d13bb..e9d1ef4 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -121,6 +121,7 @@ static bool test_event_context(struct torture_context *test, #endif int finished=0; struct timeval t; + int ret; ev_ctx = tevent_context_init_byname(test, backend); if (ev_ctx == NULL) { @@ -135,7 +136,8 @@ static bool test_event_context(struct torture_context *test, fde_count = 0; /* create a pipe */ - pipe(fd); + ret = pipe(fd); + torture_assert_int_equal(test, ret, 0, "pipe failed"); fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ, fde_handler_read, fd); -- 1.9.1 From ec2bdc1fa16ca4295d3e2c01af33f53086a7c6a6 Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Wed, 29 Apr 2015 11:34:10 -0700 Subject: [PATCH 02/14] lib: tevent: Fix compile error in Solaris ports backend. Signed-off-by: Gordon Ross Reviewed-by: Jeremy Allison Reviewed-by: Michael Adam (cherry picked from commit a7d41e94603d789bb461b84380a8fba3f837bc4f) --- lib/tevent/tevent_port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c index dd4958e..5b487d7 100644 --- a/lib/tevent/tevent_port.c +++ b/lib/tevent/tevent_port.c @@ -174,10 +174,11 @@ static int associate_all_events(struct port_event_context *port_ev) struct port_associate_vals *val; for (val = port_ev->po_vals; val; val = val->next) { + int ret; if (val->associated_event) { continue; } - int ret = port_associate(port_ev->port_fd, + ret = port_associate(port_ev->port_fd, PORT_SOURCE_FD, (uintptr_t)val->fde->fd, val->events, -- 1.9.1 From 536da861abed7db9ea59dfdc6ea2c6e1f89ba688 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 18 May 2015 13:25:33 +0200 Subject: [PATCH 03/14] tevent: add a note to tevent_add_fd() BUG: https://bugzilla.samba.org/show_bug.cgi?id=11141 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 33ca0179ac091c8bb1c2b3fa7999cc5047d09a80) --- lib/tevent/tevent.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index c54cbe2..6861ffb 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -176,6 +176,11 @@ void tevent_set_default_backend(const char *backend); * * @note To cancel the monitoring of a file descriptor, call talloc_free() * on the object returned by this function. + * + * @note The caller should avoid closing the file descriptor before + * calling talloc_free()! Otherwise the behaviour is undefined which + * might result in crashes. See https://bugzilla.samba.org/show_bug.cgi?id=11141 + * for an example. */ struct tevent_fd *tevent_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, -- 1.9.1 From 0e7249aa16ea7e9e9c80bebff6ec3049a42eec69 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 2 Jun 2015 12:18:22 +0200 Subject: [PATCH 04/14] tevent: fix access after free in tevent_common_check_signal() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was reported by Pavel Březina : We found a crash in SSSD when a tevent signal is freed in its handler, tevent than crashes when it access siginfo. sig_info is freed in signal destructor: > #ifdef SA_SIGINFO > if (se->sa_flags & SA_SIGINFO) { > if (sig_state->sig_info[se->signum]) { > talloc_free(sig_state->sig_info[se->signum]); > sig_state->sig_info[se->signum] = NULL; > } > } > #endif (gdb) bt #0 0x00007f5d4d86cc74 in tevent_signal_destructor (se=0x7f5d5370f920) at ../tevent_signal.c:213 #1 0x00007f5d4d65f233 in _talloc_free_internal () from /lib64/libtalloc.so.2 #2 0x00007f5d4d6593a3 in _talloc_free () from /lib64/libtalloc.so.2 #3 0x00007f5d4342f3d4 in proxy_child_init_done (subreq=0x7f5d5370f600) at src/providers/proxy/proxy_auth.c:436 #4 0x00007f5d4d86b0c2 in _tevent_req_error (req=req@entry=0x7f5d5370f600, error=error@entry=5, location=location@entry=0x7f5d43433010 "src/providers/proxy/proxy_auth.c:356") at ../tevent_req.c:167 #5 0x00007f5d4342ef5e in pc_init_sig_handler (ev=, sige=, signum=, count=, __siginfo=, pvt=) at src/providers/proxy/proxy_auth.c:356 #6 0x00007f5d4d86d48c in tevent_common_check_signal (ev=0x7f5d536de670) at ../tevent_signal.c:428 #7 0x00007f5d4d86f28c in epoll_event_loop (tvalp=0x7fff7b568490, epoll_ev=0x7f5d536de8b0) at ../tevent_epoll.c:647 #8 epoll_event_loop_once (ev=, location=) at ../tevent_epoll.c:926 #9 0x00007f5d4d86d7d7 in std_event_loop_once (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:114 #10 0x00007f5d4d869fbd in _tevent_loop_once (ev=ev@entry=0x7f5d536de670, location=location@entry=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:530 #11 0x00007f5d4d86a15b in tevent_common_loop_wait (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:634 #12 0x00007f5d4d86d777 in std_event_loop_wait (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:140 #13 0x00007f5d50f96863 in server_loop (main_ctx=0x7f5d536dfac0) at src/util/server.c:668 #14 0x00007f5d5180aa42 in main (argc=8, argv=) at src/providers/data_provider_be.c:2909 But then it is accessed again in tevent_common_check_signal: > #ifdef SA_SIGINFO > if (clear_processed_siginfo) { > uint32_t j; > for (j=0;j uint32_t ofs = (counter.seen + j) > % TEVENT_SA_INFO_QUEUE_COUNT; > memset((void*)&sig_state->sig_info[i][ofs], > '\0', > sizeof(siginfo_t)); > } > } > #endif (gdb) bt #0 0x00007fd7ba400505 in memset (__len=, __ch=, __dest=) at /usr/include/bits/string3.h:84 #1 tevent_common_check_signal (ev=0x7fd7bfddf670) at ../tevent_signal.c:459 #2 0x00007fd7ba40228c in epoll_event_loop (tvalp=0x7fff85536430, epoll_ev=0x7fd7bfddf8b0) at ../tevent_epoll.c:647 #3 epoll_event_loop_once (ev=, location=) at ../tevent_epoll.c:926 #4 0x00007fd7ba4007d7 in std_event_loop_once (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:114 #5 0x00007fd7ba3fcfbd in _tevent_loop_once (ev=ev@entry=0x7fd7bfddf670, location=location@entry=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:530 #6 0x00007fd7ba3fd15b in tevent_common_loop_wait (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:634 #7 0x00007fd7ba400777 in std_event_loop_wait (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:140 #8 0x00007fd7bdb29343 in server_loop (main_ctx=0x7fd7bfde0ac0) at src/util/server.c:668 #9 0x00007fd7be39ca42 in main (argc=8, argv=) at src/providers/data_provider_be.c:2909 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11308 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Jun 2 21:02:11 CEST 2015 on sn-devel-104 (cherry picked from commit 9d797ffb27bf4be100c900b0373f62b029679de3) --- lib/tevent/tevent_signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index b54da2e..924dc05 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -457,7 +457,7 @@ int tevent_common_check_signal(struct tevent_context *ev) } #ifdef SA_SIGINFO - if (clear_processed_siginfo) { + if (clear_processed_siginfo && sig_state->sig_info[i] != NULL) { uint32_t j; for (j=0;j Date: Thu, 4 Dec 2014 12:44:56 +0100 Subject: [PATCH 05/14] pytevent: Better error and reference handling py_backend_list: - Handle cases of PyString_FromString or PyList_Append failing. - Properly decrease the reference count of the returned strings. py_register_backend: - Decref "name" after use Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit f5838df58ea36e64cd0295b595df9cbd10d8c757) --- lib/tevent/pytevent.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index af3f9d6..4de0e3d 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -177,14 +177,18 @@ static PyObject *py_register_backend(PyObject *self, PyObject *args) if (!PyString_Check(name)) { PyErr_SetNone(PyExc_TypeError); + Py_DECREF(name); return NULL; } if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ PyErr_SetNone(PyExc_RuntimeError); + Py_DECREF(name); return NULL; } + Py_DECREF(name); + Py_RETURN_NONE; } @@ -684,9 +688,10 @@ static PyObject *py_set_default_backend(PyObject *self, PyObject *args) static PyObject *py_backend_list(PyObject *self) { - PyObject *ret; - int i; - const char **backends; + PyObject *ret = NULL; + PyObject *string = NULL; + int i, result; + const char **backends = NULL; ret = PyList_New(0); if (ret == NULL) { @@ -696,16 +701,30 @@ static PyObject *py_backend_list(PyObject *self) backends = tevent_backend_list(NULL); if (backends == NULL) { PyErr_SetNone(PyExc_RuntimeError); - Py_DECREF(ret); - return NULL; + goto err; } for (i = 0; backends[i]; i++) { - PyList_Append(ret, PyString_FromString(backends[i])); + string = PyString_FromString(backends[i]); + if (!string) { + goto err; + } + result = PyList_Append(ret, string); + if (result) { + goto err; + } + Py_DECREF(string); + string = NULL; } talloc_free(backends); return ret; + +err: + Py_XDECREF(ret); + Py_XDECREF(string); + talloc_free(backends); + return NULL; } static PyMethodDef tevent_methods[] = { -- 1.9.1 From 782b9863fee7644a10db22dfc0e6f4109f18420a Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 22 May 2015 13:29:11 +0200 Subject: [PATCH 06/14] pytevent: Define missing TeventFd_Type object The type objects for Fd was declared but never defined, resulting in segfaults when it was used. Define it. Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit 4399dc582fa06b04e1cec1d3aa59cd332e4b5ba2) --- lib/tevent/pytevent.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 4de0e3d..a495da5 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -415,6 +415,19 @@ static void py_fd_handler(struct tevent_context *ev, Py_XDECREF(ret); } +static void py_tevent_fp_dealloc(TeventFd_Object *self) +{ + talloc_free(self->fd); + PyObject_Del(self); +} + +static PyTypeObject TeventFd_Type = { + .tp_name = "tevent.Fd", + .tp_basicsize = sizeof(TeventFd_Object), + .tp_dealloc = (destructor)py_tevent_fp_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args) { int fd, flags; -- 1.9.1 From e8c13c134f1d7ef2ef8e08d5f784e13404b5968f Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 26 May 2015 13:25:12 +0200 Subject: [PATCH 07/14] pytalloc: Improve timer wrapper, and test it Using Context.add_timer resulted in crashes due to missing type object and bad reference handling. Add a TeventTimer_Type struct, and introduce a clear ownership/lifetime model. Add a "add_timer_offset" to allow adding timers from Python. (add_timer requires passing struct timeval as a Python integer, which can't really be done portably). Add tests. Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (similar to commit 560576217f11b132f9c32de6e41c623dbc152137) (We don't run the tests in the backport) --- lib/tevent/bindings.py | 52 ++++++++++++++++- lib/tevent/pytevent.c | 147 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 181 insertions(+), 18 deletions(-) diff --git a/lib/tevent/bindings.py b/lib/tevent/bindings.py index 1060caf..55aafbb 100644 --- a/lib/tevent/bindings.py +++ b/lib/tevent/bindings.py @@ -22,8 +22,10 @@ # License along with this library; if not, see . import signal +from unittest import TestCase, TestProgram +import gc + import _tevent -from unittest import TestCase class BackendListTests(TestCase): @@ -60,3 +62,51 @@ class ContextTests(TestCase): def test_add_signal(self): sig = self.ctx.add_signal(signal.SIGINT, 0, lambda callback: None) self.assertTrue(isinstance(sig, _tevent.Signal)) + + def test_timer(self): + """Test a timer is can be scheduled""" + collecting_list = [] + # time "0" has already passed, callback will be scheduled immediately + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertFalse(timer.active) + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_timer(self): + """Test timer is scheduled even if reference to it isn't held""" + collecting_list = [] + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + gc.collect() + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_context(self): + """Test timer is unscheduled when context is freed""" + collecting_list = [] + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + del self.ctx + gc.collect() + self.assertEqual(collecting_list, []) + self.assertFalse(timer.active) + + def test_timer_offset(self): + """Test scheduling timer with an offset""" + collecting_list = [] + self.ctx.add_timer_offset(0.2, lambda t: collecting_list.append(2)) + self.ctx.add_timer_offset(0.1, lambda t: collecting_list.append(1)) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1]) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1, 2]) + +if __name__ == '__main__': + TestProgram() diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index a495da5..a04d565 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -50,6 +50,7 @@ typedef struct { typedef struct { PyObject_HEAD struct tevent_timer *timer; + PyObject *callback; } TeventTimer_Object; typedef struct { @@ -372,38 +373,148 @@ static void py_timer_handler(struct tevent_context *ev, struct timeval current_time, void *private_data) { - PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, "l", te); + TeventTimer_Object *self = private_data; + PyObject *ret; + + ret = PyObject_CallFunction(self->callback, "l", te); + if (ret == NULL) { + /* No Python stack to propagate exception to; just print traceback */ + PyErr_PrintEx(0); + } Py_XDECREF(ret); } -static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +static void py_tevent_timer_dealloc(TeventTimer_Object *self) { - TeventTimer_Object *ret; - struct timeval next_event; - struct tevent_timer *timer; - PyObject *handler; - if (!PyArg_ParseTuple(args, "lO", &next_event, &handler)) - return NULL; - - timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, - handler); - if (timer == NULL) { - PyErr_SetNone(PyExc_RuntimeError); - return NULL; + if (self->timer) { + talloc_free(self->timer); } + Py_DECREF(self->callback); + PyObject_Del(self); +} + +static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg) +{ + Py_VISIT(self->callback); + return 0; +} + +static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self) { + return PyBool_FromLong(self->timer != NULL); +} + +struct PyGetSetDef py_tevent_timer_getset[] = { + { + .name = "active", + .get = (getter)py_tevent_timer_get_active, + .doc = "true if the timer is scheduled to run", + }, + {NULL}, +}; + +static PyTypeObject TeventTimer_Type = { + .tp_name = "tevent.Timer", + .tp_basicsize = sizeof(TeventTimer_Object), + .tp_dealloc = (destructor)py_tevent_timer_dealloc, + .tp_traverse = (traverseproc)py_tevent_timer_traverse, + .tp_getset = py_tevent_timer_getset, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +static int timer_destructor(void* ptr) +{ + TeventTimer_Object *obj = *(TeventTimer_Object **)ptr; + obj->timer = NULL; + Py_DECREF(obj); + return 0; +} + +static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self, + struct timeval next_event, + PyObject *callback) +{ + /* Ownership notes: + * + * There are 5 pieces in play; two tevent contexts and 3 Python objects: + * - The tevent timer + * - The tevent context + * - The Python context -- "self" + * - The Python timer (TeventTimer_Object) -- "ret" + * - The Python callback function -- "callback" + * + * We only use the Python context for getting the tevent context, + * afterwards it can be destroyed. + * + * The tevent context owns the tevent timer. + * + * The tevent timer holds a reference to the Python timer, so the Python + * timer must always outlive the tevent timer. + * The Python timer has a pointer to the tevent timer; a destructor is + * used to set this to NULL when the tevent timer is deallocated. + * + * The tevent timer can be deallocated in these cases: + * 1) when the context is destroyed + * 2) after the event fires + * Posssibly, API might be added to cancel (free the tevent timer). + * + * The Python timer holds a reference to the callback. + */ + TeventTimer_Object *ret; + TeventTimer_Object **tmp_context; ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); if (ret == NULL) { PyErr_NoMemory(); - talloc_free(timer); return NULL; } - ret->timer = timer; + Py_INCREF(callback); + ret->callback = callback; + ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, + ret); + if (ret->timer == NULL) { + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + tmp_context = talloc(ret->timer, TeventTimer_Object*); + if (tmp_context == NULL) { + talloc_free(ret->timer); + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + Py_INCREF(ret); + *tmp_context = ret; + talloc_set_destructor(tmp_context, timer_destructor); return (PyObject *)ret; } +static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + PyObject *callback; + if (!PyArg_ParseTuple(args, "lO", &next_event, &callback)) + return NULL; + + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + +static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + double offset; + int seconds; + PyObject *callback; + if (!PyArg_ParseTuple(args, "dO", &offset, &callback)) + return NULL; + + seconds = offset; + offset -= seconds; + next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000)); + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + static void py_fd_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, @@ -479,6 +590,8 @@ static PyMethodDef py_tevent_context_methods[] = { METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" }, { "add_timer", (PyCFunction)py_tevent_context_add_timer, METH_VARARGS, "S.add_timer(next_event, handler) -> timer" }, + { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset, + METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, #ifdef TEVENT_DEPRECATED -- 1.9.1 From 17a3f47076cc22c3975accf9f955e86bd878db24 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 22 May 2015 11:47:56 +0200 Subject: [PATCH 08/14] pytevent: Port to Python 3 - Use PyStr (String on py2, Unicode on py3) for text strings - Use PyLong instead of PyInt on Python 3 - Use new module initialization Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit 8dbdd27526c4d5358bc2614e90f9aca36f41ed1a) --- lib/tevent/pytevent.c | 70 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index a04d565..5725ae3 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -25,6 +25,17 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define PyStr_Check PyUnicode_Check +#define PyStr_FromString PyUnicode_FromString +#define PyStr_AsUTF8 PyUnicode_AsUTF8 +#define PyInt_FromLong PyLong_FromLong +#else +#define PyStr_Check PyString_Check +#define PyStr_FromString PyString_FromString +#define PyStr_AsUTF8 PyString_AsString +#endif + void init_tevent(void); typedef struct { @@ -176,13 +187,13 @@ static PyObject *py_register_backend(PyObject *self, PyObject *args) return NULL; } - if (!PyString_Check(name)) { + if (!PyStr_Check(name)) { PyErr_SetNone(PyExc_TypeError); Py_DECREF(name); return NULL; } - if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ + if (!tevent_register_backend(PyStr_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ PyErr_SetNone(PyExc_RuntimeError); Py_DECREF(name); return NULL; @@ -830,7 +841,7 @@ static PyObject *py_backend_list(PyObject *self) goto err; } for (i = 0; backends[i]; i++) { - string = PyString_FromString(backends[i]); + string = PyStr_FromString(backends[i]); if (!string) { goto err; } @@ -863,31 +874,48 @@ static PyMethodDef tevent_methods[] = { { NULL }, }; -void init_tevent(void) +#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "_tevent", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = tevent_methods, +}; +#endif + +PyObject * module_init(void); +PyObject * module_init(void) { PyObject *m; if (PyType_Ready(&TeventContext_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventQueue_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventReq_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventSignal_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventTimer_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventFd_Type) < 0) - return; + return NULL; - m = Py_InitModule3("_tevent", tevent_methods, "Tevent integration for twisted."); +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); +#endif if (m == NULL) - return; + return NULL; Py_INCREF(&TeventContext_Type); PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type); @@ -907,5 +935,21 @@ void init_tevent(void) Py_INCREF(&TeventFd_Type); PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type); - PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION)); + PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION); + + return m; +} + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit__tevent(void); +PyMODINIT_FUNC PyInit__tevent(void) +{ + return module_init(); +} +#else +void init_tevent(void); +void init_tevent(void) +{ + module_init(); } +#endif -- 1.9.1 From 08ac4fb8628c3a1b43181aa540c477b6211a339c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 30 May 2015 01:42:08 +0200 Subject: [PATCH 09/14] tevent/testsuite: make sure we cleanup tevent_fd structures in the correct order First we need to remove the tevent_fd structures without tevent_fd_set_auto_close(). Closing the fd needs to be the last thing... BUG: https://bugzilla.samba.org/show_bug.cgi?id=11316 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 88971d4870a197f656ef912911ca1e4ff5b56749) --- lib/tevent/testsuite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index e9d1ef4..c63c878 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -177,10 +177,10 @@ static bool test_event_context(struct torture_context *test, } } - talloc_free(fde_read); - talloc_free(fde_write); talloc_free(fde_read_1); talloc_free(fde_write_1); + talloc_free(fde_read); + talloc_free(fde_write); while (alarm_count < fde_count+1) { if (tevent_loop_once(ev_ctx) == -1) { -- 1.9.1 From 7366971bf2e958d5b6a48f8e2465344e578028ca Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 May 2015 09:32:26 +0200 Subject: [PATCH 10/14] tevent.h: propose tstream_ versions of read_packet_send/recv and writev_send/recv The functions operating on the raw file descriptor are for advanced callers, which take extra care and avoid the problems of https://bugzilla.samba.org/show_bug.cgi?id=11141. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11316 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 44584f810720602201a9afaaa087eeb83579eff5) --- lib/tevent/tevent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 6861ffb..b6c39d1 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -616,8 +616,8 @@ void tevent_get_trace_callback(struct tevent_context *ev, * file descriptor (tevent_add_fd) and timer (tevent_add_timed) events * are considered too low-level to be used in larger computations. To * read and write from and to sockets, Samba provides two calls on top - * of tevent_add_fd: read_packet_send/recv and writev_send/recv. These - * requests are much easier to compose than the low-level event + * of tevent_add_fd: tstream_read_packet_send/recv and tstream_writev_send/recv. + * These requests are much easier to compose than the low-level event * handlers called from tevent_add_fd. * * A lot of the simplicity tevent_req has brought to the notoriously -- 1.9.1 From 70cabfe661a3cab77f5e32dd416a974f441a86bf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:49:18 +0200 Subject: [PATCH 11/14] pytevent: remove dead code TEVENT_DEPRECATED is never defined Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 1a8a5ba0d51f9c2c9e84a3400e05327e7059156b) --- lib/tevent/pytevent.c | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 5725ae3..7f9eaf1 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -295,38 +295,6 @@ static PyObject *py_tevent_context_loop_once(TeventContext_Object *self) Py_RETURN_NONE; } -#ifdef TEVENT_DEPRECATED -static bool py_tevent_finished(PyObject *callback) -{ - PyObject *py_ret; - bool ret; - - py_ret = PyObject_CallFunction(callback, ""); - if (py_ret == NULL) - return true; - ret = PyObject_IsTrue(py_ret); - Py_DECREF(py_ret); - return ret; -} - -static PyObject *py_tevent_context_loop_until(TeventContext_Object *self, PyObject *args) -{ - PyObject *callback; - if (!PyArg_ParseTuple(args, "O", &callback)) - return NULL; - - if (tevent_loop_until(self->ev, py_tevent_finished, callback) != 0) { - PyErr_SetNone(PyExc_RuntimeError); - return NULL; - } - - if (PyErr_Occurred()) - return NULL; - - Py_RETURN_NONE; -} -#endif - static void py_tevent_signal_handler(struct tevent_context *ev, struct tevent_signal *se, int signum, @@ -576,14 +544,6 @@ static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject * return (PyObject *)ret; } -#ifdef TEVENT_DEPRECATED -static PyObject *py_tevent_context_set_allow_nesting(TeventContext_Object *self) -{ - tevent_loop_allow_nesting(self->ev); - Py_RETURN_NONE; -} -#endif - static PyMethodDef py_tevent_context_methods[] = { { "reinitialise", (PyCFunction)py_tevent_context_reinitialise, METH_NOARGS, "S.reinitialise()" }, @@ -593,10 +553,6 @@ static PyMethodDef py_tevent_context_methods[] = { METH_NOARGS, "S.loop_wait()" }, { "loop_once", (PyCFunction)py_tevent_context_loop_once, METH_NOARGS, "S.loop_once()" }, -#ifdef TEVENT_DEPRECATED - { "loop_until", (PyCFunction)py_tevent_context_loop_until, - METH_VARARGS, "S.loop_until(callback)" }, -#endif { "add_signal", (PyCFunction)py_tevent_context_add_signal, METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" }, { "add_timer", (PyCFunction)py_tevent_context_add_timer, @@ -605,10 +561,6 @@ static PyMethodDef py_tevent_context_methods[] = { METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, -#ifdef TEVENT_DEPRECATED - { "allow_nesting", (PyCFunction)py_tevent_context_set_allow_nesting, - METH_NOARGS, "Whether to allow nested tevent loops." }, -#endif { NULL }, }; -- 1.9.1 From c238b0d726cfc90b48e9e90ad80cb0084c59f9dd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:50:35 +0200 Subject: [PATCH 12/14] pytevent: remove const warnings using discard_const_p() Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit fb04f0f4190005ff21817b79d02897af23ddc7ee) --- lib/tevent/pytevent.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 7f9eaf1..03d1858 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -23,6 +23,7 @@ */ #include +#include "replace.h" #include #if PY_MAJOR_VERSION >= 3 @@ -230,7 +231,7 @@ static void py_queue_trigger(struct tevent_req *req, void *private_data) { PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, ""); + ret = PyObject_CallFunction(callback, discard_const_p(char, "")); Py_XDECREF(ret); } @@ -304,7 +305,7 @@ static void py_tevent_signal_handler(struct tevent_context *ev, { PyObject *callback = (PyObject *)private_data, *ret; - ret = PyObject_CallFunction(callback, "ii", signum, count); + ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count); Py_XDECREF(ret); } @@ -355,7 +356,7 @@ static void py_timer_handler(struct tevent_context *ev, TeventTimer_Object *self = private_data; PyObject *ret; - ret = PyObject_CallFunction(self->callback, "l", te); + ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te); if (ret == NULL) { /* No Python stack to propagate exception to; just print traceback */ PyErr_PrintEx(0); @@ -384,9 +385,9 @@ static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self) { struct PyGetSetDef py_tevent_timer_getset[] = { { - .name = "active", + .name = discard_const_p(char, "active"), .get = (getter)py_tevent_timer_get_active, - .doc = "true if the timer is scheduled to run", + .doc = discard_const_p(char, "true if the timer is scheduled to run"), }, {NULL}, }; @@ -501,7 +502,7 @@ static void py_fd_handler(struct tevent_context *ev, { PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, "i", flags); + ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags); Py_XDECREF(ret); } @@ -595,8 +596,11 @@ static PyObject *py_tevent_req_is_in_progress(PyObject *self) } static PyGetSetDef py_tevent_req_getsetters[] = { - { "in_progress", (getter)py_tevent_req_is_in_progress, NULL, - "Whether the request is in progress" }, + { + .name = discard_const_p(char, "in_progress"), + .get = (getter)py_tevent_req_is_in_progress, + .doc = discard_const_p(char, "Whether the request is in progress"), + }, { NULL } }; @@ -684,8 +688,11 @@ static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self) } static PyGetSetDef py_tevent_queue_getsetters[] = { - { "length", (getter)py_tevent_queue_get_length, - NULL, "The number of elements in the queue." }, + { + .name = discard_const_p(char, "length"), + .get = (getter)py_tevent_queue_get_length, + .doc = discard_const_p(char, "The number of elements in the queue."), + }, { NULL }, }; @@ -711,8 +718,11 @@ static PyObject *py_tevent_context_signal_support(PyObject *_self) } static PyGetSetDef py_tevent_context_getsetters[] = { - { "signal_support", (getter)py_tevent_context_signal_support, - NULL, "if this platform and tevent context support signal handling" }, + { + .name = discard_const_p(char, "signal_support"), + .get = (getter)py_tevent_context_signal_support, + .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), + }, { NULL } }; @@ -729,7 +739,7 @@ static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObj struct tevent_context *ev; TeventContext_Object *ret; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwnames, &name)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name)) return NULL; if (name == NULL) { -- 1.9.1 From 541a102b1fea0f41d8dfe2c8c3bcbd6ce345dfd0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:51:19 +0200 Subject: [PATCH 13/14] pytevent: add a TeventTimer_Object_ref helper structure to make the code clearer This gives talloc_set_destructor to verify the type, which removes a compiler warning. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 93ee074f912da02d4c1f1584df9b107364b639be) --- lib/tevent/pytevent.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 03d1858..10d8a22 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -401,11 +401,14 @@ static PyTypeObject TeventTimer_Type = { .tp_flags = Py_TPFLAGS_DEFAULT, }; -static int timer_destructor(void* ptr) +struct TeventTimer_Object_ref { + TeventTimer_Object *obj; +}; + +static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref) { - TeventTimer_Object *obj = *(TeventTimer_Object **)ptr; - obj->timer = NULL; - Py_DECREF(obj); + ref->obj->timer = NULL; + Py_DECREF(ref->obj); return 0; } @@ -440,7 +443,7 @@ static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self * The Python timer holds a reference to the callback. */ TeventTimer_Object *ret; - TeventTimer_Object **tmp_context; + struct TeventTimer_Object_ref *ref; ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); if (ret == NULL) { @@ -456,16 +459,17 @@ static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); return NULL; } - tmp_context = talloc(ret->timer, TeventTimer_Object*); - if (tmp_context == NULL) { + ref = talloc(ret->timer, struct TeventTimer_Object_ref); + if (ref == NULL) { talloc_free(ret->timer); Py_DECREF(ret); PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); return NULL; } Py_INCREF(ret); - *tmp_context = ret; - talloc_set_destructor(tmp_context, timer_destructor); + ref->obj = ret; + + talloc_set_destructor(ref, TeventTimer_Object_ref_destructor); return (PyObject *)ret; } -- 1.9.1 From a9390661d3ba2be5545b0af0cce6b14256519703 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 12 Jun 2015 08:58:26 +0200 Subject: [PATCH 14/14] tevent: version 0.9.25 * Fix compile error in Solaris ports backend. * Fix access after free in tevent_common_check_signal(). bug #11308 * Improve pytevent bindings. * Testsuite fixes. * Improve the documentation of the tevent_add_fd() assumtions. It must be talloc_free'ed before closing the fd! See bug #11141 and bug #11316. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit d7bdb30cc1731dc84831e323332a85be2bccf6a7) --- lib/tevent/ABI/tevent-0.9.25.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.25.sigs diff --git a/lib/tevent/ABI/tevent-0.9.25.sigs b/lib/tevent/ABI/tevent-0.9.25.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.25.sigs @@ -0,0 +1,88 @@ +_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *) +_tevent_loop_once: int (struct tevent_context *, const char *) +_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *) +_tevent_loop_wait: int (struct tevent_context *, const char *) +_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *) +_tevent_req_callback_data: void *(struct tevent_req *) +_tevent_req_cancel: bool (struct tevent_req *, const char *) +_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *) +_tevent_req_data: void *(struct tevent_req *) +_tevent_req_done: void (struct tevent_req *, const char *) +_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *) +_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *) +_tevent_req_notify_callback: void (struct tevent_req *, const char *) +_tevent_req_oom: void (struct tevent_req *, const char *) +_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) +tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_check_signal: int (struct tevent_context *) +tevent_common_context_destructor: int (struct tevent_context *) +tevent_common_fd_destructor: int (struct tevent_fd *) +tevent_common_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_common_loop_immediate: bool (struct tevent_context *) +tevent_common_loop_timer_delay: struct timeval (struct tevent_context *) +tevent_common_loop_wait: int (struct tevent_context *, const char *) +tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_context_init: struct tevent_context *(TALLOC_CTX *) +tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *) +tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_set_auto_close: void (struct tevent_fd *) +tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (void) +tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_length: size_t (struct tevent_queue *) +tevent_queue_running: bool (struct tevent_queue *) +tevent_queue_start: void (struct tevent_queue *) +tevent_queue_stop: void (struct tevent_queue *) +tevent_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *) +tevent_re_initialise: int (struct tevent_context *) +tevent_register_backend: bool (const char *, const struct tevent_ops *) +tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *) +tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *) +tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *) +tevent_req_is_in_progress: bool (struct tevent_req *) +tevent_req_poll: bool (struct tevent_req *, struct tevent_context *) +tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *) +tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *) +tevent_req_received: void (struct tevent_req *) +tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *) +tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn) +tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn) +tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +tevent_sa_info_queue_count: size_t (void) +tevent_set_abort_fn: void (void (*)(const char *)) +tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *) +tevent_set_debug_stderr: int (struct tevent_context *) +tevent_set_default_backend: void (const char *) +tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) +tevent_signal_support: bool (struct tevent_context *) +tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t) +tevent_timeval_compare: int (const struct timeval *, const struct timeval *) +tevent_timeval_current: struct timeval (void) +tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t) +tevent_timeval_is_zero: bool (const struct timeval *) +tevent_timeval_set: struct timeval (uint32_t, uint32_t) +tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *) +tevent_timeval_zero: struct timeval (void) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 0da8232..9abbd9b 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.24' +VERSION = '0.9.25' blddir = 'bin' -- 1.9.1