diff options
author | Pavel Březina <pbrezina@redhat.com> | 2013-01-21 17:18:30 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-01-22 15:29:00 +0100 |
commit | fa0c1419af9e95754836ed74c74596ab3296380c (patch) | |
tree | 59b0d88ee8b1da5be03e46370e5968f48864fecc /src/providers | |
parent | 45c1f3c6e3d6b2c9cf209a7b134e69e65ae7f636 (diff) | |
download | sssd-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.
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/data_provider_callbacks.c | 24 |
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")); |