andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
Blob Blame History Raw
From 574de972761ac0602dcbce14a4f98dc2fd37874d Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri, 1 Nov 2013 14:24:55 -0700
Subject: [PATCH 145/225] Ticket #47581 - Winsync plugin segfault during
 incremental backoff

Bug description: Once WinSync backoff timer is set, even if the
protocol that the backoff timer belongs to is deleted by removing
the windows sync agreement, the timer is not deleted from the event
queue.  Thus the timer is expired and backoff is called, it crashes
the server since the protocol handle is already freed, then.

Fix description: Make sure to delete the backoff timer when
1) a windows sync agreement is removed and the protocol is deleted, and
2) a new backoff timer set and there is already a backoff timer set up.

In addition to commit d70e66b2157ce3ba40c5e1cb074c2d5c150ddc5b,
the 389-ds-base-1.2.11 patch includes this change that is already made
on 389-ds-base-1.3.1 and newer.
  windows_inc_run
+   if(dirsync){
+       int rc = slapi_eq_cancel(dirsync);
+   }

https://fedorahosted.org/389/ticket/47581

(cherry picked from commit d70e66b2157ce3ba40c5e1cb074c2d5c150ddc5b)
(cherry picked from commit 91d45ff69388e529225ad729c2f48cc35c57c4f4)
---
 .../plugins/replication/windows_inc_protocol.c     | 66 ++++++++++++++--------
 1 file changed, 41 insertions(+), 25 deletions(-)

diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c
index 15d69a3..321d1a2 100644
--- a/ldap/servers/plugins/replication/windows_inc_protocol.c
+++ b/ldap/servers/plugins/replication/windows_inc_protocol.c
@@ -157,27 +157,34 @@ static Slapi_Eq_Context dirsync;
 static void
 windows_inc_delete(Private_Repl_Protocol **prpp)
 {
-	LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_inc_delete\n" );
-	/* First, stop the protocol if it isn't already stopped */
-	/* Then, delete all resources used by the protocol */
-	slapi_eq_cancel(dirsync); 
-
-        if (!(*prpp)->stopped) {
-                (*prpp)->stopped = 1;
-                (*prpp)->stop(*prpp);
-        }
-        if ((*prpp)->lock) {
-                PR_DestroyLock((*prpp)->lock);
-                (*prpp)->lock = NULL;
-        }
-        if ((*prpp)->cvar) {
-                PR_DestroyCondVar((*prpp)->cvar);
-                (*prpp)->cvar = NULL;
-        }
-        slapi_ch_free((void **)&(*prpp)->private);
-        slapi_ch_free((void **)prpp);
-
-	LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_inc_delete\n" );
+    int rc;
+    windows_inc_private *prp_priv = (windows_inc_private *)(*prpp)->private;
+    LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_inc_delete\n" );
+    /* First, stop the protocol if it isn't already stopped */
+    /* Then, delete all resources used by the protocol */
+    rc = slapi_eq_cancel(dirsync); 
+    slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+                    "windows_inc_delete: dirsync: %p, rval: %d\n", dirsync, rc);
+    /* if backoff is set, delete it (from EQ, as well) */
+    if (prp_priv->backoff) {
+        backoff_delete(&prp_priv->backoff);
+    }
+    if (!(*prpp)->stopped) {
+        (*prpp)->stopped = 1;
+        (*prpp)->stop(*prpp);
+    }
+    if ((*prpp)->lock) {
+        PR_DestroyLock((*prpp)->lock);
+        (*prpp)->lock = NULL;
+    }
+    if ((*prpp)->cvar) {
+        PR_DestroyCondVar((*prpp)->cvar);
+        (*prpp)->cvar = NULL;
+    }
+    slapi_ch_free((void **)&(*prpp)->private);
+    slapi_ch_free((void **)prpp);
+
+    LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_inc_delete\n" );
 }
 
 /* helper function */
@@ -357,7 +364,6 @@ windows_inc_run(Private_Repl_Protocol *prp)
 					w_set_pause_and_busy_time(&pausetime, &busywaittime);
 				}
 
-
 				if (is_first_start) {
 					unsigned long interval = windows_private_get_sync_interval(prp->agmt) * 1000;
 					/*
@@ -365,6 +371,12 @@ windows_inc_run(Private_Repl_Protocol *prp)
 					 * and the repeat interval. 
 					 */ 
 					/* DBDB: we should probably make this polling interval configurable */
+					if(dirsync){
+						int rc = slapi_eq_cancel(dirsync);
+						slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+						                "windows_inc_runs: cancelled dirsync: %p, rval: %d\n",
+						                dirsync, rc);
+					}
 					dirsync = slapi_eq_repeat(periodic_dirsync, (void*) prp, (time_t)0 , interval);
 					is_first_start = PR_FALSE;
 				}
@@ -606,7 +618,11 @@ windows_inc_run(Private_Repl_Protocol *prp)
 				  }
 				else
 				  {
-							/* Set up the backoff timer to wake us up at the appropriate time */
+					/* Set up the backoff timer to wake us up at the appropriate time */
+					/* if previous backoff set up, delete it. */
+					if (prp_priv->backoff) {
+						backoff_delete(&prp_priv->backoff);
+					}
 					if (use_busy_backoff_timer)
 					{
 					  /* we received a busy signal from the consumer, wait for a while */
@@ -651,14 +667,14 @@ windows_inc_run(Private_Repl_Protocol *prp)
 						run_dirsync = PR_TRUE;
 
 						windows_conn_set_agmt_changed(prp->conn);
-								/* Destroy the backoff timer, since we won't need it anymore */ 
+						/* Destroy the backoff timer, since we won't need it anymore */ 
 						if (prp_priv->backoff)   
 						  backoff_delete(&prp_priv->backoff);
 					  }
 					else if (event_occurred(prp, EVENT_WINDOW_CLOSED))
 					  {
 						next_state = STATE_WAIT_WINDOW_OPEN;
-								/* Destroy the backoff timer, since we won't need it anymore */
+						/* Destroy the backoff timer, since we won't need it anymore */
 						if (prp_priv->backoff)
 						  backoff_delete(&prp_priv->backoff);
 					  }
-- 
1.8.1.4