]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
ITS#5328: Make relay_back_has_subordinates() return failure on failure
[openldap] / servers / slapd / syncrepl.c
index fdf79b0849fb6c8eabe9fe9fdbbe77cb30ec634f..6b16e0470f9530c75a725cdabf1134b281d8d091 100644 (file)
@@ -1256,11 +1256,13 @@ do_syncrepl(
        int rc = LDAP_SUCCESS;
        int dostop = 0;
        ber_socket_t s;
-       int i, defer = 1, fail = 0;
+       int i, defer = 1, fail = 0, freeinfo = 0;
        Backend *be;
 
        if ( si == NULL )
                return NULL;
+       if ( slapd_shutdown )
+               return NULL;
 
        Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 );
 
@@ -1272,8 +1274,9 @@ do_syncrepl(
                        ldap_pvt_thread_yield();
        }
 
-       if ( !si->si_ctype )
+       if ( si->si_ctype < 1 ) {
                goto deleted;
+       }
 
        switch( abs( si->si_type ) ) {
        case LDAP_SYNC_REFRESH_ONLY:
@@ -1300,10 +1303,6 @@ do_syncrepl(
        connection_fake_init( &conn, &opbuf, ctx );
        op = &opbuf.ob_op;
 
-       /* use global malloc for now */
-       op->o_tmpmemctx = NULL;
-       op->o_tmpmfuncs = &ch_mfuncs;
-
        op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
        be = si->si_be;
 
@@ -1364,7 +1363,11 @@ reload:
 
 deleted:
                /* We got deleted while running on cn=config */
-               if ( !si->si_ctype ) {
+               if ( si->si_ctype < 1 ) {
+                       if ( si->si_ctype == -1 ) {
+                               si->si_ctype = 0;
+                               freeinfo = 1;
+                       }
                        if ( si->si_conn )
                                dostop = 1;
                        rc = -1;
@@ -1431,7 +1434,7 @@ deleted:
                                break;
                }
 
-               if ( !si->si_ctype
+               if ( si->si_ctype < 1
                        || !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) {
                        if ( si->si_re ) {
                                ldap_pvt_runqueue_remove( &slapd_rq, rtask );
@@ -1468,7 +1471,7 @@ deleted:
        }
 
        /* Do final delete cleanup */
-       if ( !si->si_ctype ) {
+       if ( freeinfo ) {
                syncinfo_free( si, 0 );
        }
        return NULL;
@@ -1624,7 +1627,16 @@ syncrepl_message_to_op(
 
                if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn ) ) {
                        bdn = bvals[0];
-                       dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+                       rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+                       if ( rc != LDAP_SUCCESS ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "syncrepl_message_to_op: %s "
+                                       "dn \"%s\" normalization failed (%d)",
+                                       si->si_ridtxt, bdn.bv_val, rc );
+                               rc = -1;
+                               ch_free( bvals );
+                               goto done;
+                       }
                        ber_dupbv( &op->o_req_dn, &dn );
                        ber_dupbv( &op->o_req_ndn, &ndn );
                        slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
@@ -1856,7 +1868,21 @@ syncrepl_message_to_entry(
                return -1;
        }
 
-       dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+       rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+       if ( rc != LDAP_SUCCESS ) {
+               /* One of the things that could happen is that the schema
+                * is not lined-up; this could result in unknown attributes.
+                * A value non conformant to the syntax should be unlikely,
+                * except when replicating between different versions
+                * of the software, or when syntax validation bugs are fixed
+                */
+               Debug( LDAP_DEBUG_ANY,
+                       "syncrepl_message_to_entry: "
+                       "%s dn \"%s\" normalization failed (%d)",
+                       si->si_ridtxt, bdn.bv_val, rc );
+               return rc;
+       }
+
        ber_dupbv( &op->o_req_dn, &dn );
        ber_dupbv( &op->o_req_ndn, &ndn );
        slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
@@ -3602,13 +3628,6 @@ syncinfo_free( syncinfo_t *sie, int free_all )
        Debug( LDAP_DEBUG_TRACE, "syncinfo_free: %s\n",
                sie->si_ridtxt, 0, 0 );
 
-       sie->si_cookieState->cs_ref--;
-       if ( !sie->si_cookieState->cs_ref ) {
-               ch_free( sie->si_cookieState->cs_sids );
-               ber_bvarray_free( sie->si_cookieState->cs_vals );
-               ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
-               ch_free( sie->si_cookieState );
-       }
        do {
                si_next = sie->si_next;
 
@@ -3620,20 +3639,21 @@ syncinfo_free( syncinfo_t *sie, int free_all )
                        ldap_unbind_ext( sie->si_ld, NULL, NULL );
                }
        
-               /* re-fetch it, in case it was already removed */
-               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-               sie->si_re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, sie );
                if ( sie->si_re ) {
-                       if ( ldap_pvt_runqueue_isrunning( &slapd_rq, sie->si_re ) )
-                               ldap_pvt_runqueue_stoptask( &slapd_rq, sie->si_re );
-                       ldap_pvt_runqueue_remove( &slapd_rq, sie->si_re );
+                       struct re_s             *re = sie->si_re;
+                       sie->si_re = NULL;
+
+                       ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+                       if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
+                               ldap_pvt_runqueue_stoptask( &slapd_rq, re );
+                       ldap_pvt_runqueue_remove( &slapd_rq, re );
+                       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                }
-       
-               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-               ldap_pvt_thread_mutex_destroy( &sie->si_mutex );
-       
+
+               ldap_pvt_thread_mutex_destroy( &sie->si_mutex );
+
                bindconf_free( &sie->si_bindconf );
-       
+
                if ( sie->si_filterstr.bv_val ) {
                        ch_free( sie->si_filterstr.bv_val );
                }
@@ -3709,6 +3729,13 @@ syncinfo_free( syncinfo_t *sie, int free_all )
                        }
                        ch_free( npe );
                }
+               sie->si_cookieState->cs_ref--;
+               if ( !sie->si_cookieState->cs_ref ) {
+                       ch_free( sie->si_cookieState->cs_sids );
+                       ber_bvarray_free( sie->si_cookieState->cs_vals );
+                       ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
+                       ch_free( sie->si_cookieState );
+               }
                ch_free( sie );
                sie = si_next;
        } while ( free_all && si_next );
@@ -4378,7 +4405,7 @@ add_syncrepl(
 
                        si->si_cookieState = c->be->be_syncinfo->si_cookieState;
 
-                       // add new syncrepl to end of list (same order as when deleting)
+                       /* add new syncrepl to end of list (same order as when deleting) */
                        for ( sip = c->be->be_syncinfo; sip->si_next; sip = sip->si_next );
                        sip->si_next = si;
                } else {
@@ -4602,29 +4629,29 @@ syncrepl_config( ConfigArgs *c )
                                        if ( si->si_re ) {
                                                if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
                                                        isrunning = 1;
-                                               } else if ( si->si_conn ) {
-                                                       isrunning = 1;
-                                                       /* If there's a persistent connection, we don't
-                                                        * know if it's already got a thread queued.
-                                                        * so defer the free, but reschedule the task.
-                                                        * If there's a connection thread queued, it
-                                                        * will cleanup as necessary. If not, then the
-                                                        * runqueue task will cleanup.
-                                                        */
-                                                       ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-                                                       if ( !ldap_pvt_runqueue_isrunning( &slapd_rq, si->si_re )) {
-                                                               si->si_re->interval.tv_sec = 0;
-                                                               ldap_pvt_runqueue_resched( &slapd_rq, si->si_re, 0 );
-                                                               si->si_re->interval.tv_sec = si->si_interval;
-                                                       }
-                                                       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-
                                                } else {
+                                                       if ( si->si_conn ) {
+                                                               isrunning = 1;
+                                                               /* If there's a persistent connection, we don't
+                                                                * know if it's already got a thread queued.
+                                                                * so defer the free, but reschedule the task.
+                                                                * If there's a connection thread queued, it
+                                                                * will cleanup as necessary. If not, then the
+                                                                * runqueue task will cleanup.
+                                                                */
+                                                               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+                                                               if ( !ldap_pvt_runqueue_isrunning( &slapd_rq, si->si_re )) {
+                                                                       si->si_re->interval.tv_sec = 0;
+                                                                       ldap_pvt_runqueue_resched( &slapd_rq, si->si_re, 0 );
+                                                                       si->si_re->interval.tv_sec = si->si_interval;
+                                                               }
+                                                               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+                                                       }
                                                        ldap_pvt_thread_mutex_unlock( &si->si_mutex );
                                                }
                                        }
                                        if ( isrunning ) {
-                                               si->si_ctype = 0;
+                                               si->si_ctype = -1;
                                                si->si_next = NULL;
                                        } else {
                                                syncinfo_free( si, 0 );