daemon: Run an external script if freeze locks were not obtained during recovery
authorAmitay Isaacs <amitay@gmail.com>
Wed, 5 Dec 2012 00:37:26 +0000 (11:37 +1100)
committerMartin Schwenke <martin@meltin.net>
Wed, 8 May 2013 04:14:50 +0000 (14:14 +1000)
If the freeze child is already created in ctdb_start_freeze(), then it indicates
that the child process has not yet obtained the locks.  This may be because
another process has locked the databases and has not yet released the locks.

In this case, invoke a helper script defined by environmental variable
CTDB_DEBUG_LOCKS, to log information about locks.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
(cherry picked from commit e80b2c15bf8c8fb5c3793acfebbe09d3cdd617b7)

server/ctdb_freeze.c

index 0f70fd35023df539dceab412195cd741fed02a9c..f422e6d8cc8f1eb596cf702069fc21fd7ed8444e 100644 (file)
@@ -255,6 +255,26 @@ static int ctdb_freeze_waiter_destructor(struct ctdb_freeze_waiter *w)
        return 0;
 }
 
+/*
+ * Run an external script to check if there is a deadlock situation
+ */
+static void ctdb_debug_locks(void)
+{
+       const char *cmd = getenv("CTDB_DEBUG_LOCKS");
+       int pid;
+
+       if (cmd == NULL) {
+               return;
+       }
+
+       pid = fork();
+
+       /* Execute only in child process */
+       if (pid == 0) {
+               execl(cmd, cmd, NULL);
+       }
+}
+
 /*
   start the freeze process for a certain priority
  */
@@ -283,6 +303,10 @@ int ctdb_start_freeze(struct ctdb_context *ctdb, uint32_t priority)
                ctdb->freeze_handles[priority] = ctdb_freeze_lock(ctdb, priority);
                CTDB_NO_MEMORY(ctdb, ctdb->freeze_handles[priority]);
                ctdb->freeze_mode[priority] = CTDB_FREEZE_PENDING;
+       } else {
+               /* The previous free lock child has not yet been able to get locks.
+                * Invoke debugging script */
+               ctdb_debug_locks();
        }
 
        return 0;