Ver Fonte

Allow call sam_warn_signal_set after sam_register

Patch fixes situation, when user want to change warn signal after
call of sam_register function. This was not possible, because parent
process never got new value from child.


git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@2821 fd59a12c-fef9-0310-b244-a6a79926bd2f
Jan Friesse há 15 anos atrás
pai
commit
088a2a0f17
3 ficheiros alterados com 278 adições e 29 exclusões
  1. 1 1
      lib/libsam.verso
  2. 109 23
      lib/sam.c
  3. 168 5
      test/testsam.c

+ 1 - 1
lib/libsam.verso

@@ -1 +1 @@
-4.2.0
+4.2.1

+ 109 - 23
lib/sam.c

@@ -73,6 +73,7 @@ enum sam_command_t {
 	SAM_COMMAND_STOP,
 	SAM_COMMAND_HB,
 	SAM_COMMAND_DATA_STORE,
+	SAM_COMMAND_WARN_SIGNAL_SET,
 };
 
 enum sam_reply_t {
@@ -194,6 +195,40 @@ static size_t sam_safe_read (
 	return (bytes_read);
 }
 
+static cs_error_t sam_read_reply (
+	int child_fd_in)
+{
+	char reply;
+	cs_error_t err;
+
+	if (sam_safe_read (sam_internal_data.child_fd_in, &reply, sizeof (reply)) != sizeof (reply)) {
+		return (CS_ERR_LIBRARY);
+	}
+
+	switch (reply) {
+	case SAM_REPLY_ERROR:
+		/*
+		 * Read error and return that
+		 */
+		if (sam_safe_read (sam_internal_data.child_fd_in, &err, sizeof (err)) != sizeof (err)) {
+			return (CS_ERR_LIBRARY);
+		}
+
+		return (err);
+		break;
+	case SAM_REPLY_OK:
+		/*
+		 * Everything correct
+		 */
+		break;
+	default:
+		return (CS_ERR_LIBRARY);
+		break;
+	}
+
+	return (CS_OK);
+}
+
 cs_error_t sam_data_getsize (size_t *size)
 {
 	if (size == NULL) {
@@ -247,7 +282,6 @@ cs_error_t sam_data_store (
 	cs_error_t err;
 	char command;
 	char *new_data;
-	char reply;
 
 	if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
 		sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
@@ -290,29 +324,8 @@ cs_error_t sam_data_store (
 		/*
 		 * And wait for reply
 		 */
-		if (sam_safe_read (sam_internal_data.child_fd_in, &reply, sizeof (reply)) != sizeof (reply)) {
-			return (CS_ERR_LIBRARY);
-		}
-
-		switch (reply) {
-		case SAM_REPLY_ERROR:
-			/*
-			 * Read error and return that
-			 */
-			if (sam_safe_read (sam_internal_data.child_fd_in, &err, sizeof (err)) != sizeof (err)) {
-				return (CS_ERR_LIBRARY);
-			}
-
+		if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
 			return (err);
-			break;
-		case SAM_REPLY_OK:
-			/*
-			 * Everything correct
-			 */
-			break;
-		default:
-			return (CS_ERR_LIBRARY);
-			break;
 		}
 	}
 
@@ -421,17 +434,87 @@ exit_error:
 
 cs_error_t sam_warn_signal_set (int warn_signal)
 {
+	char command;
+	cs_error_t err;
+
 	if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
 		sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
 		sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
 		return (CS_ERR_BAD_HANDLE);
 	}
 
+	if (sam_internal_data.am_i_child) {
+		/*
+		 * We are child so we must send data to parent
+		 */
+		command = SAM_COMMAND_WARN_SIGNAL_SET;
+		if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command)) {
+			return (CS_ERR_LIBRARY);
+		}
+
+		if (sam_safe_write (sam_internal_data.child_fd_out, &warn_signal, sizeof (warn_signal)) !=
+		   sizeof (warn_signal)) {
+			return (CS_ERR_LIBRARY);
+		}
+
+		/*
+		 * And wait for reply
+		 */
+		if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
+			return (err);
+		}
+	}
+
+	/*
+	 * We are parent or we received OK reply from parent -> do required action
+	 */
 	sam_internal_data.warn_signal = warn_signal;
 
 	return (CS_OK);
 }
 
+static cs_error_t sam_parent_warn_signal_set (
+	int parent_fd_in,
+	int parent_fd_out)
+{
+	char reply;
+	char *user_data;
+	int warn_signal;
+	cs_error_t err;
+
+	err = CS_OK;
+	user_data = NULL;
+
+	if (sam_safe_read (parent_fd_in, &warn_signal, sizeof (warn_signal)) != sizeof (warn_signal)) {
+		err = CS_ERR_LIBRARY;
+		goto error_reply;
+	}
+
+	err = sam_warn_signal_set (warn_signal);
+	if (err != CS_OK) {
+		goto error_reply;
+	}
+
+	reply = SAM_REPLY_OK;
+	if (sam_safe_write (parent_fd_out, &reply, sizeof (reply)) != sizeof (reply)) {
+		err = CS_ERR_LIBRARY;
+		goto error_reply;
+	}
+
+	return (CS_OK);
+
+error_reply:
+	reply = SAM_REPLY_ERROR;
+	if (sam_safe_write (parent_fd_out, &reply, sizeof (reply)) != sizeof (reply)) {
+		return (CS_ERR_LIBRARY);
+	}
+	if (sam_safe_write (parent_fd_out, &err, sizeof (err)) != sizeof (err)) {
+		return (CS_ERR_LIBRARY);
+	}
+
+	return (err);
+}
+
 static cs_error_t sam_parent_data_store (
 	int parent_fd_in,
 	int parent_fd_out)
@@ -604,6 +687,9 @@ static enum sam_parent_action_t sam_parent_handler (
 			case SAM_COMMAND_DATA_STORE:
 				sam_parent_data_store (parent_fd_in, parent_fd_out);
 				break;
+			case SAM_COMMAND_WARN_SIGNAL_SET:
+				sam_parent_warn_signal_set (parent_fd_in, parent_fd_out);
+				break;
 			}
 		} /* select_error > 0 */
 	} /* action == SAM_PARENT_ACTION_CONTINUE */

+ 168 - 5
test/testsam.c

@@ -51,6 +51,7 @@
 
 static int test2_sig_delivered = 0;
 static int test5_hc_cb_count = 0;
+static int test6_sig_delivered = 0;
 
 /*
  * First test will just register SAM, with policy restart. First instance will
@@ -597,6 +598,142 @@ static int test5 (void)
 	return 1;
 }
 
+static void test6_signal (int sig) {
+	cs_error_t error;
+
+	printf ("%s\n", __FUNCTION__);
+	test6_sig_delivered++;
+
+	if ((error = sam_data_store (&test6_sig_delivered, sizeof (test6_sig_delivered))) != CS_OK) {
+		fprintf (stderr, "Can't store data! Error : %d\n", error);
+	}
+}
+
+/*
+ * Test warn signal set.
+ */
+static int test6 (void) {
+	cs_error_t error;
+	unsigned int instance_id;
+	int test6_sig_del;
+
+	printf ("%s: initialize\n", __FUNCTION__);
+	error = sam_initialize (2000, SAM_RECOVERY_POLICY_RESTART);
+	if (error != CS_OK) {
+		fprintf (stderr, "Can't initialize SAM API. Error %d\n", error);
+		return 1;
+	}
+	printf ("%s: register\n", __FUNCTION__);
+	error = sam_register (&instance_id);
+	if (error != CS_OK) {
+		fprintf (stderr, "Can't register. Error %d\n", error);
+		return 1;
+	}
+
+	if (instance_id == 1) {
+		error = sam_warn_signal_set (SIGUSR1);
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't set warn signal. Error %d\n", error);
+			return 1;
+		}
+
+		signal (SIGUSR1, test6_signal);
+
+		printf ("%s iid %d: start\n", __FUNCTION__, instance_id);
+		error = sam_start ();
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't start hc. Error %d\n", error);
+			return 1;
+		}
+
+		printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id);
+		sleep (1);
+
+		printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id);
+		error = sam_hc_send ();
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't send hc. Error %d\n", error);
+			return 1;
+		}
+
+
+		printf ("%s iid %d: wait for delivery of signal\n", __FUNCTION__, instance_id);
+		while (!test6_sig_delivered) {
+			sleep (1);
+		}
+
+		printf ("%s iid %d: wait for real kill\n", __FUNCTION__, instance_id);
+
+		sleep (3);
+
+		printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id);
+		return (1);
+	}
+
+	if (instance_id == 2) {
+		error = sam_data_restore (&test6_sig_del, sizeof (test6_sig_del));
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't restore data. Error %d\n", error);
+			return 1;
+		}
+
+		if (test6_sig_del != 1) {
+			fprintf (stderr, "Previous test failed. Signal was not delivered\n");
+			return 1;
+		}
+
+		error = sam_warn_signal_set (SIGKILL);
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't set warn signal. Error %d\n", error);
+			return 1;
+		}
+
+		signal (SIGUSR1, test6_signal);
+
+		printf ("%s iid %d: start\n", __FUNCTION__, instance_id);
+		error = sam_start ();
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't start hc. Error %d\n", error);
+			return 1;
+		}
+
+		printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id);
+		sleep (1);
+
+		printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id);
+		error = sam_hc_send ();
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't send hc. Error %d\n", error);
+			return 1;
+		}
+
+
+		printf ("%s iid %d: wait for delivery of signal\n", __FUNCTION__, instance_id);
+		while (!test6_sig_delivered) {
+			sleep (1);
+		}
+
+		printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id);
+		return (1);
+	}
+
+	if (instance_id == 3) {
+		error = sam_data_restore (&test6_sig_del, sizeof (test6_sig_del));
+		if (error != CS_OK) {
+			fprintf (stderr, "Can't restore data. Error %d\n", error);
+			return 1;
+		}
+
+		if (test6_sig_del != 1) {
+			fprintf (stderr, "Previous test failed. Signal WAS delivered\n");
+			return 1;
+		}
+
+		return (0);
+	}
+
+	return 1;
+}
 
 int main(int argc, char *argv[])
 {
@@ -613,7 +750,9 @@ int main(int argc, char *argv[])
 	}
 
 	if (pid == 0) {
-		return (test1 ());
+		err = test1 ();
+		sam_finalize ();
+		return err;
 	}
 
 	waitpid (pid, &stat, 0);
@@ -632,7 +771,8 @@ int main(int argc, char *argv[])
 	if (pid == 0) {
 		err = test2 ();
 
-		return err;
+		sam_finalize ();
+		return (err);
 	}
 
 	waitpid (pid, &stat, 0);
@@ -649,7 +789,9 @@ int main(int argc, char *argv[])
 	}
 
 	if (pid == 0) {
-		return (test3 ());
+		err = test3 ();
+		sam_finalize ();
+		return (err);
 	}
 
 	waitpid (pid, &stat, 0);
@@ -666,7 +808,9 @@ int main(int argc, char *argv[])
 	}
 
 	if (pid == 0) {
-		return (test4 ());
+		err = test4 ();
+		sam_finalize ();
+		return (err);
 	}
 
 	waitpid (pid, &stat, 0);
@@ -685,7 +829,8 @@ int main(int argc, char *argv[])
 	if (pid == 0) {
 		err = test5 ();
 
-		return err;
+		sam_finalize ();
+		return (err);
 	}
 
 	waitpid (pid, &stat, 0);
@@ -693,6 +838,24 @@ int main(int argc, char *argv[])
 	if (WEXITSTATUS (stat) != 0)
 		all_passed = 0;
 
+	pid = fork ();
+
+	if (pid == -1) {
+		fprintf (stderr, "Can't fork\n");
+		return 1;
+	}
+
+	if (pid == 0) {
+		err = test6 ();
+		sam_finalize ();
+		return (err);
+	}
+
+	waitpid (pid, &stat, 0);
+	fprintf (stderr, "test6 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed"));
+	if (WEXITSTATUS (stat) != 0)
+		all_passed = 0;
+
 	if (all_passed)
 		fprintf (stderr, "All tests passed\n");