[SCM] CTDB repository - branch master updated - c4c2c53918da6fb566d6e9cbd6b02e61ae2921e7

Ronnie Sahlberg sahlberg at samba.org
Sun May 11 04:33:10 GMT 2008


The branch, master has been updated
       via  c4c2c53918da6fb566d6e9cbd6b02e61ae2921e7 (commit)
      from  d36f6a5ceb57364449b246a4e6664a7da6cb0040 (commit)

http://gitweb.samba.org/?p=sahlberg/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c4c2c53918da6fb566d6e9cbd6b02e61ae2921e7
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Sun May 11 14:28:33 2008 +1000

    ctdb->methods becomes NULL when we shutdown the transport.
    
    If we shutdown the transport   and CTDB later decides to send a command out
    for queueing, the call to ctdb->methods->allocate_pkt() will SEGV.
    
    This could trigger for example when we are in the process of shuttind down CTDBD and have already shutdown the transport but we are still waiting for the
    "shutdown" eventscripts to finish.
    If the event scripts now take much much longer to execute for some reason, this
    race condition becomes much more probable.
    
    Decorate all dereferencing of ctdb->methods->    with a check that ctdb->menthods is non-NULL

-----------------------------------------------------------------------

Summary of changes:
 server/ctdb_control.c  |    4 +++-
 server/ctdb_daemon.c   |   16 ++++++++++++++++
 server/ctdb_recover.c  |    9 ++++++++-
 server/ctdb_recoverd.c |    8 ++++++--
 server/ctdb_server.c   |   10 ++++++++++
 5 files changed, 43 insertions(+), 4 deletions(-)


Changeset truncated at 500 lines:

diff --git a/server/ctdb_control.c b/server/ctdb_control.c
index 6c8a4fc..6a2a9ce 100644
--- a/server/ctdb_control.c
+++ b/server/ctdb_control.c
@@ -276,7 +276,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 		ctdb_stop_keepalive(ctdb);
 		ctdb_stop_monitoring(ctdb);
 		ctdb_release_all_ips(ctdb);
-		ctdb->methods->shutdown(ctdb);
+		if (ctdb->methods != NULL) {
+			ctdb->methods->shutdown(ctdb);
+		}
 		ctdb_event_script(ctdb, "shutdown");
 		DEBUG(DEBUG_NOTICE,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
 		exit(0);
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index 93af56c..326ab60 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -71,6 +71,11 @@ static void print_exit_message(void)
 /* called when the "startup" event script has finished */
 static void ctdb_start_transport(struct ctdb_context *ctdb)
 {
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " startup event finished but transport is DOWN.\n"));
+		ctdb_fatal(ctdb, "transport is not initialized but startup completed");
+	}
+
 	/* start the transport running */
 	if (ctdb->methods->start(ctdb) != 0) {
 		DEBUG(DEBUG_ALERT,("transport failed to start!\n"));
@@ -689,6 +694,11 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork)
 		return -1;
 	}
 
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not initialize transport. ctdb->methods is NULL\n"));
+		ctdb_fatal(ctdb, "transport is unavailable. can not initialize.");
+	}
+
 	/* initialise the transport  */
 	if (ctdb->methods->initialise(ctdb) != 0) {
 		ctdb_fatal(ctdb, "transport failed to initialise");
@@ -743,6 +753,12 @@ struct ctdb_req_header *_ctdb_transport_allocate(struct ctdb_context *ctdb,
 	length = MAX(length, slength);
 	size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
 
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " Unable to allocate transport packet for operation %u of length %u. Transport is DOWN.\n",
+			 operation, (unsigned)length));
+		return NULL;
+	}
+
 	hdr = (struct ctdb_req_header *)ctdb->methods->allocate_pkt(mem_ctx, size);
 	if (hdr == NULL) {
 		DEBUG(DEBUG_ERR,("Unable to allocate transport packet for operation %u of length %u\n",
diff --git a/server/ctdb_recover.c b/server/ctdb_recover.c
index 7a96733..3da3b56 100644
--- a/server/ctdb_recover.c
+++ b/server/ctdb_recover.c
@@ -180,7 +180,9 @@ ctdb_reload_nodes_event(struct event_context *ev, struct timed_event *te,
 	int ctdb_tcp_init(struct ctdb_context *);
 
 	/* shut down the transport */
-	ctdb->methods->shutdown(ctdb);
+	if (ctdb->methods != NULL) {
+		ctdb->methods->shutdown(ctdb);
+	}
 
 	/* start the transport again */
 	ctdb_load_nodes_file(ctdb);
@@ -189,6 +191,11 @@ ctdb_reload_nodes_event(struct event_context *ev, struct timed_event *te,
 		DEBUG(DEBUG_CRIT, (__location__ " Failed to init TCP\n"));
 		exit(1);
 	}
+
+	if (ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not restart transport. ctdb->methods==NULL\n"));
+		ctdb_fatal(ctdb, "can not reinitialize transport.");
+	}
 	ctdb->methods->initialise(ctdb);
 	ctdb->methods->start(ctdb);
 
diff --git a/server/ctdb_recoverd.c b/server/ctdb_recoverd.c
index 95dd94f..7aca7cb 100644
--- a/server/ctdb_recoverd.c
+++ b/server/ctdb_recoverd.c
@@ -2790,7 +2790,9 @@ static void ctdb_check_recd(struct event_context *ev, struct timed_event *te,
 		ctdb_stop_keepalive(ctdb);
 		ctdb_stop_monitoring(ctdb);
 		ctdb_release_all_ips(ctdb);
-		ctdb->methods->shutdown(ctdb);
+		if (ctdb->methods != NULL) {
+			ctdb->methods->shutdown(ctdb);
+		}
 		ctdb_event_script(ctdb, "shutdown");
 
 		exit(10);	
@@ -2831,7 +2833,9 @@ int ctdb_start_recoverd(struct ctdb_context *ctdb)
 	close(fd[1]);
 
 	/* shutdown the transport */
-	ctdb->methods->shutdown(ctdb);
+	if (ctdb->methods) {
+		ctdb->methods->shutdown(ctdb);
+	}
 
 	/* get a new event context */
 	talloc_free(ctdb->ev);
diff --git a/server/ctdb_server.c b/server/ctdb_server.c
index 546d618..a4c09a9 100644
--- a/server/ctdb_server.c
+++ b/server/ctdb_server.c
@@ -345,6 +345,11 @@ void ctdb_node_dead(struct ctdb_node *node)
 		 node->ctdb->name, node->name, node->ctdb->num_connected));
 	ctdb_daemon_cancel_controls(node->ctdb, node);
 
+	if (node->ctdb->methods == NULL) {
+		DEBUG(DEBUG_ALERT,(__location__ " Can not restart transport. ctdb->methods==NULL\n"));
+		ctdb_fatal(node->ctdb, "can not restart transport.");
+	}
+
 	node->ctdb->methods->restart(node);
 }
 
@@ -484,6 +489,11 @@ void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 	if (hdr->destnode == ctdb->pnn) {
 		ctdb_defer_packet(ctdb, hdr);
 	} else {
+		if (ctdb->methods == NULL) {
+			DEBUG(DEBUG_ALERT, (__location__ " Can not queue packet. Transport is DOWN\n"));
+			return;
+		}
+
 		node->tx_cnt++;
 		if (ctdb->methods->queue_pkt(node, (uint8_t *)hdr, hdr->length) != 0) {
 			ctdb_fatal(ctdb, "Unable to queue packet\n");


-- 
CTDB repository


More information about the samba-cvs mailing list