diff --git a/libraries/libldap_r/rq.c b/libraries/libldap_r/rq.c
index b028054e33a17a75defa29715ef2e21b8c4301f2..194d16db8eda17e77969da03b883bbc064771bde 100644
--- a/libraries/libldap_r/rq.c
+++ b/libraries/libldap_r/rq.c
@@ -66,12 +66,11 @@ ldap_pvt_runqueue_remove(
 			break;
 	}
 
-	assert ( e == entry );
-
-	LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
+	if ( e == entry ) {
+		LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
+	}
 
 	LDAP_FREE( entry );
-
 }
 
 struct re_s*
@@ -148,7 +147,7 @@ ldap_pvt_runqueue_resched(
 
 	LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
 
-	if ( entry->interval.tv_sec && !defer ) {
+	if ( !defer ) {
 		entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
 	} else {
 		entry->next_sched.tv_sec = 0;
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 7aceee21eb25fd94d5a8701df5cc7a506ad1bd6e..b91b0979dfa05dec53f6f03c17ae7981c756c0e0 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -3028,6 +3028,9 @@ add_syncrepl(
 	si->si_attrs[0] = NULL;
 	si->si_type = LDAP_SYNC_REFRESH_ONLY;
 	si->si_interval = 86400;
+	si->si_retryinterval = 0;
+	si->si_retrynum_init = 0;
+	si->si_retrynum = 0;
 	si->si_syncCookie.ctxcsn = NULL;
 	si->si_syncCookie.octet_str = NULL;
 	si->si_syncCookie.sid = -1;
@@ -3144,6 +3147,8 @@ add_syncrepl(
 #define SLIMITSTR		"sizelimit"
 #define TLIMITSTR		"timelimit"
 
+#define RETRYSTR		"retry"
+
 #define GOT_ID			0x0001
 #define GOT_PROVIDER	0x0002
 #define GOT_METHOD		0x0004
@@ -3383,6 +3388,53 @@ parse_syncrepl_line(
 					(long) si->si_interval);
 				return 1;
 			}
+		} else if ( !strncasecmp( cargv[ i ],
+			RETRYSTR, sizeof( RETRYSTR ) - 1 ) )
+		{
+			char *str;
+			char **retry_list;
+			int j, k, n;
+
+			val = cargv[ i ] + sizeof( RETRYSTR );
+			retry_list = (char **) ch_calloc( 1, sizeof( char * ));
+			retry_list[0] = NULL;
+
+			str2clist( &retry_list, val, " ,\t" );
+
+			for ( k = 0; retry_list && retry_list[k]; k++ ) ;
+			n = k / 2;
+			if ( k % 2 ) {
+				fprintf( stderr,
+						"Error: incomplete syncrepl retry list\n" );
+				for ( k = 0; retry_list && retry_list[k]; k++ ) {
+					ch_free( retry_list[k] );
+				}
+				ch_free( retry_list );
+				exit( EXIT_FAILURE );
+			}
+			si->si_retryinterval = (time_t *) ch_calloc( n + 1, sizeof( time_t ));
+			si->si_retrynum = (int *) ch_calloc( n + 1, sizeof( int ));
+			si->si_retrynum_init = (int *) ch_calloc( n + 1, sizeof( int ));
+			for ( j = 0; j < n; j++ ) {
+				si->si_retryinterval[j] = atoi( retry_list[j*2] );
+				if ( *retry_list[j*2+1] == '+' ) {
+					si->si_retrynum_init[j] = -1;
+					si->si_retrynum[j] = -1;
+					j++;
+					break;
+				} else {
+					si->si_retrynum_init[j] = atoi( retry_list[j*2+1] );
+					si->si_retrynum[j] = atoi( retry_list[j*2+1] );
+				}
+			}
+			si->si_retrynum_init[j] = -2;
+			si->si_retrynum[j] = -2;
+			si->si_retryinterval[j] = 0;
+			
+			for ( k = 0; retry_list && retry_list[k]; k++ ) {
+				ch_free( retry_list[k] );
+			}
+			ch_free( retry_list );
 		} else if ( !strncasecmp( cargv[ i ],
 			MANAGEDSAITSTR, sizeof( MANAGEDSAITSTR ) - 1 ) )
 		{
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 293c3cb79c84836cce6016c0d0c1e71f1b10c8df..e0330c07bbde4bb209657d9e697e2f39bcf2e91e 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1407,6 +1407,9 @@ typedef struct syncinfo_s {
         char				**si_attrs;
         int					si_type;
         time_t				si_interval;
+		time_t				*si_retryinterval;
+		int					*si_retrynum_init;
+		int					*si_retrynum;
 		struct sync_cookie	si_syncCookie;
         int					si_manageDSAit;
         int					si_slimit;
diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
index 530963696356eae10c37646fb7d36022c35878ca..42a3456b89277a20bc615e3aab015c386778c043 100644
--- a/servers/slapd/syncrepl.c
+++ b/servers/slapd/syncrepl.c
@@ -823,6 +823,7 @@ do_syncrepl(
 	int first = 0;
 	int dostop = 0;
 	ber_socket_t s;
+	int i, defer = 1;
 
 #ifdef NEW_LOGGING
 	LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 );
@@ -885,7 +886,7 @@ do_syncrepl(
 						arg );
 				} else {
 					connection_client_enable( s );
-				}
+				} 
 			} else if ( !first ) {
 				dostop = 1;
 			}
@@ -901,25 +902,45 @@ do_syncrepl(
 	 * 4) for Persist and Success, reschedule to defer
 	 */
 	ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex );
+
 	if ( ldap_pvt_runqueue_isrunning( &syncrepl_rq, rtask )) {
 		ldap_pvt_runqueue_stoptask( &syncrepl_rq, rtask );
 	}
 
-	if ( dostop ) {
-		connection_client_stop( s );
-	}
-
-	if ( rc && rc != LDAP_SERVER_DOWN ) {
-		ldap_pvt_runqueue_remove( &syncrepl_rq, rtask );
+	if ( rc == LDAP_SUCCESS ) {
+		if ( dostop ) {
+			connection_client_stop( s );
+		}
+		if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
+			defer = 0;
+		}
+		rtask->interval.tv_sec = si->si_interval;
+		ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, defer );
+		if ( si->si_retrynum ) {
+			for ( i = 0; si->si_retrynum_init[i] != -2; i++ ) {
+				si->si_retrynum[i] = si->si_retrynum_init[i];
+			}
+			si->si_retrynum[i] = -2;
+		}
 	} else {
-		if ( rc == LDAP_SERVER_DOWN ||
-			si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
-			rc = 0;
-		} else {
-			rc = 1;
+		for ( i = 0; si->si_retrynum && si->si_retrynum[i] <= 0; i++ ) {
+			if ( si->si_retrynum[i] == -1  || si->si_retrynum[i] == -2 )
+				break;
+		}
+
+		if ( !si->si_retrynum || si->si_retrynum[i] == -2 ) {
+			if ( dostop ) {
+				connection_client_stop( s );
+			}
+			ldap_pvt_runqueue_remove( &syncrepl_rq, rtask );
+		} else if ( si->si_retrynum[i] >= -1 ) {
+			if ( si->si_retrynum[i] > 0 )
+				si->si_retrynum[i]--;
+			rtask->interval.tv_sec = si->si_retryinterval[i];
+			ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 );
 		}
-		ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, rc );
 	}
+	
 	ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex );
 
 	return NULL;