Răsfoiți Sursa

ipcs: allow connections only after all services are ready

this fixes a rather annoying race condition at startup where a client
connects to corosync "too fast" before the service is ready to operate
and client gets some random data during initialization phase.

With this fix, we allow connections to ipc only after the main engine
is operational and configured (and after the first totem transition).

Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
Reviewed-by: Angus Salkeld <asalkeld@redhat.com>
Fabio M. Di Nitto 14 ani în urmă
părinte
comite
b34c1e2870
3 a modificat fișierele cu 14 adăugiri și 0 ștergeri
  1. 11 0
      exec/ipc_glue.c
  2. 1 0
      exec/main.c
  3. 2 0
      exec/main.h

+ 11 - 0
exec/ipc_glue.c

@@ -69,6 +69,7 @@ static int32_t ipc_not_enough_fds_left = 0;
 static int32_t ipc_fc_is_quorate; /* boolean */
 static int32_t ipc_fc_is_quorate; /* boolean */
 static int32_t ipc_fc_totem_queue_level; /* percentage used */
 static int32_t ipc_fc_totem_queue_level; /* percentage used */
 static int32_t ipc_fc_sync_in_process; /* boolean */
 static int32_t ipc_fc_sync_in_process; /* boolean */
+static int32_t ipc_allow_connections = 0; /* boolean */
 
 
 struct cs_ipcs_mapper {
 struct cs_ipcs_mapper {
 	int32_t id;
 	int32_t id;
@@ -149,6 +150,11 @@ static const char* cs_ipcs_serv_short_name(int32_t service_id)
 	return name;
 	return name;
 }
 }
 
 
+void cs_ipc_allow_connections(int32_t allow)
+{
+	ipc_allow_connections = allow;
+}
+
 int32_t cs_ipcs_service_destroy(int32_t service_id)
 int32_t cs_ipcs_service_destroy(int32_t service_id)
 {
 {
 	if (ipcs_mapper[service_id].inst) {
 	if (ipcs_mapper[service_id].inst) {
@@ -164,6 +170,11 @@ static int32_t cs_ipcs_connection_accept (qb_ipcs_connection_t *c, uid_t euid, g
 	uint8_t u8;
 	uint8_t u8;
 	char key_name[ICMAP_KEYNAME_MAXLEN];
 	char key_name[ICMAP_KEYNAME_MAXLEN];
 
 
+	if (!ipc_allow_connections) {
+		log_printf(LOGSYS_LEVEL_DEBUG, "Denied connection, corosync is not ready");
+		return -EAGAIN;
+	}
+
 	if (corosync_service[service] == NULL ||
 	if (corosync_service[service] == NULL ||
 		corosync_service_exiting[service] ||
 		corosync_service_exiting[service] ||
 		ipcs_mapper[service].inst == NULL) {
 		ipcs_mapper[service].inst == NULL) {

+ 1 - 0
exec/main.c

@@ -252,6 +252,7 @@ static void corosync_sync_completed (void)
 	sync_in_process = 0;
 	sync_in_process = 0;
 
 
 	cs_ipcs_sync_state_changed(sync_in_process);
 	cs_ipcs_sync_state_changed(sync_in_process);
+	cs_ipc_allow_connections(1);
 }
 }
 
 
 static int corosync_sync_callbacks_retrieve (
 static int corosync_sync_callbacks_retrieve (

+ 2 - 0
exec/main.h

@@ -119,6 +119,8 @@ extern void cs_ipc_refcnt_inc(void *conn);
 
 
 extern void cs_ipc_refcnt_dec(void *conn);
 extern void cs_ipc_refcnt_dec(void *conn);
 
 
+extern void cs_ipc_allow_connections(int32_t allow);
+
 int coroparse_configparse (const char **error_string);
 int coroparse_configparse (const char **error_string);
 
 
 #endif /* MAIN_H_DEFINED */
 #endif /* MAIN_H_DEFINED */