summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2013-01-21 17:18:30 +0100
committerJakub Hrozek <jhrozek@redhat.com>2013-01-22 15:29:00 +0100
commitfa0c1419af9e95754836ed74c74596ab3296380c (patch)
tree59b0d88ee8b1da5be03e46370e5968f48864fecc
parent45c1f3c6e3d6b2c9cf209a7b134e69e65ae7f636 (diff)
downloadsssd-fa0c1419af9e95754836ed74c74596ab3296380c.tar.gz
sssd-fa0c1419af9e95754836ed74c74596ab3296380c.tar.xz
sssd-fa0c1419af9e95754836ed74c74596ab3296380c.zip
fix backend callbacks: remove callback properly from dlist
https://fedorahosted.org/sssd/ticket/1776 Although cb->list got updated when the callback is removed, this change did not propagate to be_ctx->*_cb_list which caused dlist having invalid records.
-rw-r--r--src/providers/data_provider_callbacks.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
index 0f8fca0b1..3081b8df3 100644
--- a/src/providers/data_provider_callbacks.c
+++ b/src/providers/data_provider_callbacks.c
@@ -34,7 +34,7 @@ struct be_cb {
be_callback_t cb;
void *pvt;
- struct be_cb *list;
+ struct be_cb **list;
struct be_ctx *be;
};
@@ -46,7 +46,7 @@ struct be_cb_ctx {
static int cb_destructor(TALLOC_CTX *ptr)
{
struct be_cb *cb = talloc_get_type(ptr, struct be_cb);
- DLIST_REMOVE(cb->list, cb);
+ DLIST_REMOVE(*(cb->list), cb);
return 0;
}
@@ -67,7 +67,7 @@ static int be_add_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
new_cb->cb = cb;
new_cb->pvt = pvt;
- new_cb->list = *cb_list;
+ new_cb->list = cb_list;
new_cb->be = ctx;
DLIST_ADD(*cb_list, new_cb);
@@ -85,14 +85,18 @@ static void be_run_cb_step(struct tevent_context *ev, struct tevent_timer *te,
struct timeval current_time, void *pvt)
{
struct be_cb_ctx *cb_ctx = talloc_get_type(pvt, struct be_cb_ctx);
+ struct be_cb *next_cb;
struct tevent_timer *tev;
struct timeval soon;
+ /* Store next callback in case this callback frees itself */
+ next_cb = cb_ctx->callback->next;
+
/* Call the callback */
cb_ctx->callback->cb(cb_ctx->callback->pvt);
- if (cb_ctx->callback->next) {
- cb_ctx->callback = cb_ctx->callback->next;
+ if (next_cb) {
+ cb_ctx->callback = next_cb;
/* Delay 30ms so we don't block any other events */
soon = tevent_timeval_current_ofs(0, 30000);
@@ -119,6 +123,10 @@ static errno_t be_run_cb(struct be_ctx *be, struct be_cb *cb_list) {
struct tevent_timer *te;
struct be_cb_ctx *cb_ctx;
+ if (cb_list == NULL) {
+ return EOK;
+ }
+
cb_ctx = talloc(be, struct be_cb_ctx);
if (!cb_ctx) {
DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
@@ -158,6 +166,7 @@ int be_add_reconnect_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t c
void be_run_reconnect_cb(struct be_ctx *be)
{
struct be_cb *callback = be->reconnect_cb_list;
+ struct be_cb *next_cb;
if (callback) {
DEBUG(SSSDBG_TRACE_FUNC, ("Reconnecting. Running callbacks.\n"));
@@ -168,8 +177,11 @@ void be_run_reconnect_cb(struct be_ctx *be)
* a little while
*/
do {
+ /* Store next callback in case this callback frees itself */
+ next_cb = callback->next;
+
callback->cb(callback->pvt);
- callback = callback->next;
+ callback = next_cb;
} while(callback != NULL);
} else {
DEBUG(SSSDBG_TRACE_INTERNAL, ("Reconnect call back list is empty, nothing to do.\n"));