From 0599ac42ec109e944e2cd914764258a7acd2652f Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Tue, 2 Dec 2008 17:54:05 -0500 Subject: - use a counter to make sure we don't recurse inside the same thread, which might cause us to try to take a read lock when we're holding the write lock, or vice-versa --- src/back-sch.c | 40 ++++++++++++++++++++++------------------ src/back-shr.c | 36 ++++++++++++++++++++++++++++++++++++ src/wrap.c | 17 +++++++++++++++++ src/wrap.h | 4 ++++ 4 files changed, 79 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/back-sch.c b/src/back-sch.c index ef69aba..8a6486f 100644 --- a/src/back-sch.c +++ b/src/back-sch.c @@ -811,16 +811,9 @@ static int backend_search_cb(Slapi_PBlock *pb) { struct backend_search_cbdata cbdata; -#if 0 - Slapi_Operation *op; - /* If we were called to service an internal search (made by us or any - * other plugin), stop right here. */ - op = NULL; - slapi_pblock_get(pb, SLAPI_OPERATION, &op); - if (slapi_operation_is_flag_set(op, OP_FLAG_INTERNAL)) { + if (wrap_get_call_level() > 0) { return 0; } -#endif memset(&cbdata, 0, sizeof(cbdata)); cbdata.pb = pb; slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); @@ -838,25 +831,17 @@ backend_search_cb(Slapi_PBlock *pb) cbdata.closest_match = NULL; cbdata.text = NULL; cbdata.n_entries = 0; - /* If we were called to service one of our internal searches, stop - * right here. */ - if (backend_shr_is_caller(cbdata.state, cbdata.pb)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata.state->plugin_desc->spd_id, - "ignoring self-started search from \"%s\" for " - "\"%s\" with scope %d\n", - cbdata.target, cbdata.strfilter, cbdata.scope); - return 0; - } /* Okay, we can search. */ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "searching from \"%s\" for \"%s\" with scope %d\n", cbdata.target, cbdata.strfilter, cbdata.scope); cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); /* Walk the list of groups. */ + wrap_inc_call_level(); map_rdlock(); map_data_foreach_domain(cbdata.state, backend_search_group_cb, &cbdata); map_unlock(); + wrap_dec_call_level(); /* If we "own" the search target DN, then we need to send a response. */ if (cbdata.answer) { if (cbdata.matched || (cbdata.n_entries > 0)) { @@ -999,6 +984,12 @@ static int backend_write_cb(Slapi_PBlock *pb) { int ret; + + if (wrap_get_call_level() > 0) { + return 0; + } + + wrap_inc_call_level(); map_rdlock(); if (backend_check_scope_pb(pb)) { slapi_send_ldap_result(pb, LDAP_INSUFFICIENT_ACCESS, @@ -1008,6 +999,8 @@ backend_write_cb(Slapi_PBlock *pb) ret = 0; } map_unlock(); + wrap_dec_call_level(); + return ret; } @@ -1020,6 +1013,11 @@ backend_bind_cb(Slapi_PBlock *pb) struct berval *urls[] = {&ref, NULL}; const char *ndn; + if (wrap_get_call_level() > 0) { + return 0; + } + + wrap_inc_call_level(); map_rdlock(); backend_locate(pb, &data); if (data != NULL) { @@ -1046,6 +1044,7 @@ backend_bind_cb(Slapi_PBlock *pb) } } map_unlock(); + wrap_dec_call_level(); return ret; } @@ -1053,6 +1052,10 @@ static int backend_compare_cb(Slapi_PBlock *pb) { int ret; + if (wrap_get_call_level() > 0) { + return 0; + } + wrap_inc_call_level(); map_rdlock(); if (backend_check_scope_pb(pb)) { slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, @@ -1062,6 +1065,7 @@ backend_compare_cb(Slapi_PBlock *pb) ret = 0; } map_unlock(); + wrap_dec_call_level(); return ret; } diff --git a/src/back-shr.c b/src/back-shr.c index e24aa69..1edcb9e 100644 --- a/src/back-shr.c +++ b/src/back-shr.c @@ -1295,6 +1295,12 @@ backend_shr_add_cb(Slapi_PBlock *pb) { struct backend_add_entry_cbdata cbdata; + /* If we somehow recursed here from ourselves, just bail. */ + if (wrap_get_call_level() > 0) { + return 0; + } + + /* Read parameters from the pblock. */ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); slapi_pblock_get(pb, SLAPI_ADD_TARGET, &cbdata.ndn); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e); @@ -1315,6 +1321,7 @@ backend_shr_add_cb(Slapi_PBlock *pb) /* Add map entries which corresponded to this directory server * entry. */ + wrap_inc_call_level(); map_wrlock(); if (!map_data_foreach_map(cbdata.state, NULL, backend_shr_add_entry_cb, &cbdata)) { @@ -1337,6 +1344,7 @@ backend_shr_add_cb(Slapi_PBlock *pb) backend_shr_update_references(cbdata.state, cbdata.e); map_unlock(); + wrap_dec_call_level(); return 0; } @@ -1389,6 +1397,13 @@ backend_shr_modify_cb(Slapi_PBlock *pb) { Slapi_DN *sdn; struct backend_shr_modify_entry_cbdata cbdata; + + /* If we somehow recursed here from ourselves, just bail. */ + if (wrap_get_call_level() > 0) { + return 0; + } + + /* Read parameters from the pblock. */ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &cbdata.ndn); slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods); @@ -1412,6 +1427,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) } /* Modify map entries which corresponded to this directory server * entry. */ + wrap_inc_call_level(); map_wrlock(); if (!map_data_foreach_map(cbdata.state, NULL, backend_shr_modify_entry_cb, &cbdata)) { @@ -1454,6 +1470,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) slapi_sdn_free(&sdn); } map_unlock(); + wrap_dec_call_level(); return 0; } @@ -1508,9 +1525,17 @@ static int backend_shr_modrdn_cb(Slapi_PBlock *pb) { struct backend_shr_modrdn_entry_cbdata cbdata; + + /* If we somehow recursed here from ourselves, just bail. */ + if (wrap_get_call_level() > 0) { + return 0; + } + + /* Read parameters from the pblock. */ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e_post); + /* Check for NULL entries, indicative of a failure elsewhere (?). */ if (cbdata.e_pre == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -1533,6 +1558,7 @@ backend_shr_modrdn_cb(Slapi_PBlock *pb) cbdata.ndn_pre, cbdata.ndn_post); /* Modify map entries which corresponded to this directory server * entry. */ + wrap_inc_call_level(); map_wrlock(); if (!map_data_foreach_map(cbdata.state, NULL, backend_shr_modrdn_entry_cb, &cbdata)) { @@ -1558,6 +1584,7 @@ backend_shr_modrdn_cb(Slapi_PBlock *pb) backend_set_config_entry_add_cb(cbdata.e_post, cbdata.state); } map_unlock(); + wrap_dec_call_level(); return 0; } @@ -1597,6 +1624,13 @@ static int backend_shr_delete_cb(Slapi_PBlock *pb) { struct backend_shr_delete_entry_cbdata cbdata; + + /* If we somehow recursed here from ourselves, just bail. */ + if (wrap_get_call_level() > 0) { + return 0; + } + + /* Read parameters from the pblock. */ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); slapi_pblock_get(pb, SLAPI_DELETE_TARGET, &cbdata.ndn); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e); @@ -1612,6 +1646,7 @@ backend_shr_delete_cb(Slapi_PBlock *pb) } /* Remove map entries which corresponded to this directory server * entry. */ + wrap_inc_call_level(); map_wrlock(); if (!map_data_foreach_map(cbdata.state, NULL, backend_shr_delete_entry_cb, &cbdata)) { @@ -1631,6 +1666,7 @@ backend_shr_delete_cb(Slapi_PBlock *pb) * affected by this entry. */ backend_shr_update_references(cbdata.state, cbdata.e); map_unlock(); + wrap_dec_call_level(); return 0; } diff --git a/src/wrap.c b/src/wrap.c index b007aeb..c6062f8 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -272,3 +272,20 @@ wrap_search_internal_get_entry(Slapi_DN *dn, char **attrs, #endif } +static __thread int call_level = 0; + +int +wrap_get_call_level(void) +{ + return call_level; +} +int +wrap_inc_call_level(void) +{ + return ++call_level; +} +int +wrap_dec_call_level(void) +{ + return --call_level; +} diff --git a/src/wrap.h b/src/wrap.h index db530c3..211a22e 100644 --- a/src/wrap.h +++ b/src/wrap.h @@ -39,4 +39,8 @@ void wrap_rwlock_unlock(struct wrapped_rwlock *rwlock); int wrap_search_internal_get_entry(Slapi_DN *dn, char **attrs, Slapi_Entry **ret_entry, void *caller_id); +int wrap_get_call_level(void); +int wrap_inc_call_level(void); +int wrap_dec_call_level(void); + #endif -- cgit