Example #1
0
static int corosync_main_config_set (
	const char *path,
	const char *subsys,
	const char **error_string)
{
	const char *error_reason = error_string_response;
	char *value = NULL;
	int mode;
	char key_name[MAP_KEYNAME_MAXLEN];

	/*
	 * this bit abuses the internal logsys exported API
	 * to guarantee that all configured subsystems are
	 * initialized too.
	 *
	 * using this approach avoids some headaches caused
	 * by IPC and TOTEM that have a special logging
	 * handling requirements
	 */
	if (subsys != NULL) {
		if (_logsys_subsys_create(subsys, NULL) < 0) {
			error_reason = "unable to create new logging subsystem";
			goto parse_error;
		}
	}

	mode = logsys_config_mode_get(subsys);
	if (mode < 0) {
		error_reason = "unable to get mode";
		goto parse_error;
	}

	if (corosync_main_config_log_destination_set (path, "to_stderr", subsys, &error_reason,
	    LOGSYS_MODE_OUTPUT_STDERR, 0, 1, NULL) != 0)
		goto parse_error;

	if (corosync_main_config_log_destination_set (path, "to_syslog", subsys, &error_reason,
	    LOGSYS_MODE_OUTPUT_SYSLOG, 0, 1, NULL) != 0)
		goto parse_error;

	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_facility");
	if (map_get_string(key_name, &value) == CS_OK) {
		int syslog_facility;

		syslog_facility = qb_log_facility2int(value);
		if (syslog_facility < 0) {
			error_reason = "unknown syslog facility specified";
			goto parse_error;
		}
		if (logsys_config_syslog_facility_set(subsys,
						syslog_facility) < 0) {
			error_reason = "unable to set syslog facility";
			goto parse_error;
		}

		free(value);
	}
	else {
		/* Set default here in case of a reload */
		if (logsys_config_syslog_facility_set(subsys,
						      qb_log_facility2int("daemon")) < 0) {
			error_reason = "unable to set syslog facility";
			goto parse_error;
		}
	}

	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_level");
	if (map_get_string(key_name, &value) == CS_OK) {
		int syslog_priority;

		log_printf(LOGSYS_LEVEL_WARNING,
		 "Warning: the syslog_level config parameter has been obsoleted."
		 " See corosync.conf man page syslog_priority directive.");

		syslog_priority = logsys_priority_id_get(value);
		free(value);

		if (syslog_priority < 0) {
			error_reason = "unknown syslog level specified";
			goto parse_error;
		}
		if (logsys_config_syslog_priority_set(subsys,
						syslog_priority) < 0) {
			error_reason = "unable to set syslog level";
			goto parse_error;
		}
	}

	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_priority");
	if (map_get_string(key_name, &value) == CS_OK) {
		int syslog_priority;

		syslog_priority = logsys_priority_id_get(value);
		free(value);
		if (syslog_priority < 0) {
			error_reason = "unknown syslog priority specified";
			goto parse_error;
		}
		if (logsys_config_syslog_priority_set(subsys,
						syslog_priority) < 0) {
			error_reason = "unable to set syslog priority";
			goto parse_error;
		}
	}
	else {
		if (logsys_config_syslog_priority_set(subsys,
						      logsys_priority_id_get("info")) < 0) {
			error_reason = "unable to set syslog level";
			goto parse_error;
		}
	}

#ifdef LOGCONFIG_USE_ICMAP
	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "logfile");
	if (map_get_string(key_name, &value) == CS_OK) {
		if (logsys_config_file_set (subsys, &error_reason, value) < 0) {
			goto parse_error;
		}
		free(value);
	}
#else
	if (!subsys) {
		if (logsys_config_file_set (subsys, &error_reason, main_logfile) < 0) {
			goto parse_error;
		}
	}
#endif

	if (corosync_main_config_log_destination_set (path, "to_file", subsys, &error_reason,
	   LOGSYS_MODE_OUTPUT_FILE, 1, 0, "to_logfile") != 0)
		goto parse_error;

	if (corosync_main_config_log_destination_set (path, "to_logfile", subsys, &error_reason,
	   LOGSYS_MODE_OUTPUT_FILE, 0, 0, NULL) != 0)
		goto parse_error;

	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "logfile_priority");
	if (map_get_string(key_name, &value) == CS_OK) {
		int logfile_priority;

		logfile_priority = logsys_priority_id_get(value);
		free(value);
		if (logfile_priority < 0) {
			error_reason = "unknown logfile priority specified";
			goto parse_error;
		}
		if (logsys_config_logfile_priority_set(subsys,
						logfile_priority) < 0) {
			error_reason = "unable to set logfile priority";
			goto parse_error;
		}
	}
	else {
		if (logsys_config_logfile_priority_set(subsys,
						      logsys_priority_id_get("info")) < 0) {
			error_reason = "unable to set syslog level";
			goto parse_error;
		}
	}

	snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "debug");
	if (map_get_string(key_name, &value) == CS_OK) {
		if (strcmp (value, "trace") == 0) {
			if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_TRACE) < 0) {
				error_reason = "unable to set debug trace";
				free(value);
				goto parse_error;
			}
		} else
		if (strcmp (value, "on") == 0) {
			if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_ON) < 0) {
				error_reason = "unable to set debug on";
				free(value);
				goto parse_error;
			}
		} else
		if (strcmp (value, "off") == 0) {
			if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_OFF) < 0) {
				error_reason = "unable to set debug off";
				free(value);
				goto parse_error;
			}
		} else {
			error_reason = "unknown value for debug";
			free(value);
			goto parse_error;
		}
		free(value);
	}
	else {
		if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_OFF) < 0) {
			error_reason = "unable to set debug off";
			free(value);
			goto parse_error;
		}
	}

	return (0);

parse_error:
	*error_string = error_reason;

	return (-1);
}
Example #2
0
int main (int argc, char **argv)
{
	const char *error_string;
	struct totem_config totem_config;
	hdb_handle_t objdb_handle;
	hdb_handle_t config_handle;
	unsigned int config_version = 0;
	void *objdb_p;
	struct config_iface_ver0 *config;
	void *config_p;
	const char *config_iface_init;
	char *config_iface;
	char *iface;
	char *strtok_save_pt;
	int res, ch;
	int background, setprio;
	struct stat stat_out;
	char corosync_lib_dir[PATH_MAX];
	hdb_handle_t object_runtime_handle;

#if defined(HAVE_PTHREAD_SPIN_LOCK)
	pthread_spin_init (&serialize_spin, 0);
#endif

 	/* default configuration
	 */
	background = 1;
	setprio = 1;

	while ((ch = getopt (argc, argv, "fpv")) != EOF) {

		switch (ch) {
			case 'f':
				background = 0;
				logsys_config_mode_set (NULL, LOGSYS_MODE_OUTPUT_STDERR|LOGSYS_MODE_THREADED|LOGSYS_MODE_FORK);
				break;
			case 'p':
				setprio = 0;
				break;
			case 'v':
				printf ("Corosync Cluster Engine, version '%s' SVN revision '%s'\n", VERSION, SVN_REVISION);
				printf ("Copyright (c) 2006-2009 Red Hat, Inc.\n");
				return EXIT_SUCCESS;

				break;
			default:
				fprintf(stderr, \
					"usage:\n"\
					"        -f     : Start application in foreground.\n"\
					"        -p     : Do not set process priority.    \n"\
					"        -v     : Display version and SVN revision of Corosync and exit.\n");
				return EXIT_FAILURE;
		}
	}

	/*
	 * Set round robin realtime scheduling with priority 99
	 * Lock all memory to avoid page faults which may interrupt
	 * application healthchecking
	 */
	if (setprio) {
		corosync_setscheduler ();
	}

	corosync_mlockall ();

	log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Cluster Engine ('%s'): started and ready to provide service.\n", VERSION);
	log_printf (LOGSYS_LEVEL_INFO, "Corosync built-in features:" PACKAGE_FEATURES "\n");

	(void)signal (SIGINT, sigintr_handler);
	(void)signal (SIGUSR2, sigusr2_handler);
	(void)signal (SIGSEGV, sigsegv_handler);
	(void)signal (SIGABRT, sigabrt_handler);
	(void)signal (SIGQUIT, sigquit_handler);
	(void)signal (SIGTERM, sigterm_handler);
#if MSG_NOSIGNAL != 0
	(void)signal (SIGPIPE, SIG_IGN);
#endif

	/*
	 * Load the object database interface
	 */
	res = lcr_ifact_reference (
		&objdb_handle,
		"objdb",
		0,
		&objdb_p,
		0);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration object database component.\n");
		corosync_exit_error (AIS_DONE_OBJDB);
	}

	objdb = (struct objdb_iface_ver0 *)objdb_p;

	objdb->objdb_init ();

	/*
	 * Initialize the corosync_api_v1 definition
	 */
	apidef_init (objdb);
	api = apidef_get ();

	num_config_modules = 0;

	/*
	 * Bootstrap in the default configuration parser or use
	 * the corosync default built in parser if the configuration parser
	 * isn't overridden
	 */
	config_iface_init = getenv("COROSYNC_DEFAULT_CONFIG_IFACE");
	if (!config_iface_init) {
		config_iface_init = "corosync_parser";
	}

	/* Make a copy so we can deface it with strtok */
	if ((config_iface = strdup(config_iface_init)) == NULL) {
		log_printf (LOGSYS_LEVEL_ERROR, "exhausted virtual memory");
		corosync_exit_error (AIS_DONE_OBJDB);
	}

	iface = strtok_r(config_iface, ":", &strtok_save_pt);
	while (iface)
	{
		res = lcr_ifact_reference (
			&config_handle,
			iface,
			config_version,
			&config_p,
			0);

		config = (struct config_iface_ver0 *)config_p;
		if (res == -1) {
			log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration component '%s'\n", iface);
			corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
		}

		res = config->config_readconfig(objdb, &error_string);
		if (res == -1) {
			log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
			corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
		}
		log_printf (LOGSYS_LEVEL_NOTICE, "%s", error_string);
		config_modules[num_config_modules++] = config;

		iface = strtok_r(NULL, ":", &strtok_save_pt);
	}
	free(config_iface);

	res = corosync_main_config_read (objdb, &error_string);
	if (res == -1) {
		/*
		 * if we are here, we _must_ flush the logsys queue
		 * and try to inform that we couldn't read the config.
		 * this is a desperate attempt before certain death
		 * and there is no guarantee that we can print to stderr
		 * nor that logsys is sending the messages where we expect.
		 */
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		fprintf(stderr, "%s", error_string);
		syslog (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	/*
	 * Make sure required directory is present
	 */
	sprintf (corosync_lib_dir, "%s/lib/corosync", LOCALSTATEDIR);
	res = stat (corosync_lib_dir, &stat_out);
	if ((res == -1) || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
		log_printf (LOGSYS_LEVEL_ERROR, "Required directory not present %s.  Please create it.\n", corosync_lib_dir);
		corosync_exit_error (AIS_DONE_DIR_NOT_PRESENT);
	}

	res = totem_config_read (objdb, &totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	res = totem_config_keyread (objdb, &totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	res = totem_config_validate (&totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	totem_config.totem_logging_configuration = totem_logging_configuration;
	totem_config.totem_logging_configuration.log_subsys_id =
		_logsys_subsys_create ("TOTEM");

	if (totem_config.totem_logging_configuration.log_subsys_id < 0) {
		log_printf (LOGSYS_LEVEL_ERROR,
			"Unable to initialize TOTEM logging subsystem\n");
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	totem_config.totem_logging_configuration.log_level_security = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_error = LOGSYS_LEVEL_ERROR;
	totem_config.totem_logging_configuration.log_level_warning = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_notice = LOGSYS_LEVEL_NOTICE;
	totem_config.totem_logging_configuration.log_level_debug = LOGSYS_LEVEL_DEBUG;
	totem_config.totem_logging_configuration.log_printf = _logsys_log_printf;

	res = corosync_main_config_compatibility_read (objdb,
		&minimum_sync_mode,
		&error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	res = corosync_main_config_compatibility_read (objdb,
		&minimum_sync_mode,
		&error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
	}

	/* create the main runtime object */
	objdb->object_create (OBJECT_PARENT_HANDLE,
		&object_runtime_handle,
		"runtime", strlen ("runtime"));

	/*
	 * Now we are fully initialized.
	 */
	if (background) {
		corosync_tty_detach ();
	}
	logsys_fork_completed();

	corosync_timer_init (
		serialize_lock,
		serialize_unlock,
		sched_priority);

	corosync_poll_handle = poll_create ();

	/*
	 * Sleep for a while to let other nodes in the cluster
	 * understand that this node has been away (if it was
	 * an corosync restart).
	 */

// TODO what is this hack for?	usleep(totem_config.token_timeout * 2000);

	/*
	 * Create semaphore and start "exit" thread
	 */
	res = sem_init (&corosync_exit_sem, 0, 0);
	if (res != 0) {
		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't create exit thread.\n");
		corosync_exit_error (AIS_DONE_FATAL_ERR);
	}

	res = pthread_create (&corosync_exit_thread, NULL, corosync_exit_thread_handler, NULL);
	if (res != 0) {
		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't create exit thread.\n");
		corosync_exit_error (AIS_DONE_FATAL_ERR);
	}

	/*
	 * if totempg_initialize doesn't have root priveleges, it cannot
	 * bind to a specific interface.  This only matters if
	 * there is more then one interface in a system, so
	 * in this case, only a warning is printed
	 */
	/*
	 * Join multicast group and setup delivery
	 *  and configuration change functions
	 */
	totempg_initialize (
		corosync_poll_handle,
		&totem_config);

	totempg_service_ready_register (
		main_service_ready);

	totempg_groups_initialize (
		&corosync_group_handle,
		deliver_fn,
		confchg_fn);

	totempg_groups_join (
		corosync_group_handle,
		&corosync_group,
		1);

	/*
	 * Drop root privleges to user 'ais'
	 * TODO: Don't really need full root capabilities;
	 *       needed capabilities are:
	 * CAP_NET_RAW (bindtodevice)
	 * CAP_SYS_NICE (setscheduler)
	 * CAP_IPC_LOCK (mlockall)
	 */
	priv_drop ();

	schedwrk_init (
		serialize_lock,
		serialize_unlock);

	ipc_subsys_id = _logsys_subsys_create ("IPC");
	if (ipc_subsys_id < 0) {
		log_printf (LOGSYS_LEVEL_ERROR,
			"Could not initialize IPC logging subsystem\n");
		corosync_exit_error (AIS_DONE_INIT_SERVICES);
	}

	ipc_init_state_v2.log_subsys_id = ipc_subsys_id;
	coroipcs_ipc_init_v2 (&ipc_init_state_v2);

	/*
	 * Start main processing loop
	 */
	poll_run (corosync_poll_handle);

	return EXIT_SUCCESS;
}
Example #3
0
/*
 * Create an instance
 */
int totemknet_initialize (
	qb_loop_t *poll_handle,
	void **knet_context,
	struct totem_config *totem_config,
	totemsrp_stats_t *stats,
	void *context,

	void (*deliver_fn) (
		void *context,
		const void *msg,
		unsigned int msg_len),

	void (*iface_change_fn) (
		void *context,
		const struct totem_ip_address *iface_address,
		unsigned int link_no),

	void (*mtu_changed) (
		void *context,
		int net_mtu),

	void (*target_set_completed) (
		void *context))
{
	struct totemknet_instance *instance;
	int8_t channel=0;
	int res;
	int i;

	instance = malloc (sizeof (struct totemknet_instance));
	if (instance == NULL) {
		return (-1);
	}

	totemknet_instance_initialize (instance);

	instance->totem_config = totem_config;
	instance->stats = stats;

	/*
	* Configure logging
	*/
	instance->totemknet_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
	instance->totemknet_log_level_error = totem_config->totem_logging_configuration.log_level_error;
	instance->totemknet_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
	instance->totemknet_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
	instance->totemknet_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
	instance->totemknet_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
	instance->totemknet_log_printf = totem_config->totem_logging_configuration.log_printf;

	instance->knet_subsys_id = _logsys_subsys_create("KNET", "libknet.h");

	/*
	 * Initialize local variables for totemknet
	 */

	instance->our_nodeid = instance->totem_config->node_id;

	for (i=0; i< instance->totem_config->interface_count; i++) {
		totemip_copy(&instance->my_ids[i], &totem_config->interfaces[i].bindnet);
		instance->my_ids[i].nodeid = instance->our_nodeid;
		instance->ip_port[i] = totem_config->interfaces[i].ip_port;

		/* Needed for totemsrp */
		totem_config->interfaces[i].boundto.nodeid = instance->our_nodeid;
	}

	instance->poll_handle = poll_handle;

	instance->context = context;
	instance->totemknet_deliver_fn = deliver_fn;

	instance->totemknet_iface_change_fn = iface_change_fn;

	instance->totemknet_mtu_changed = mtu_changed;

	instance->totemknet_target_set_completed = target_set_completed;

	pipe(instance->logpipes);
	fcntl(instance->logpipes[0], F_SETFL, O_NONBLOCK);
	fcntl(instance->logpipes[1], F_SETFL, O_NONBLOCK);

	instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG);

	if (!instance->knet_handle) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_CRIT, "knet_handle_new failed");
		return (-1);
	}
	res = knet_handle_pmtud_setfreq(instance->knet_handle, instance->totem_config->knet_pmtud_interval);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_pmtud_setfreq failed");
	}
	res = knet_handle_enable_filter(instance->knet_handle, instance, dst_host_filter_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_filter failed");
	}
	res = knet_handle_enable_sock_notify(instance->knet_handle, instance, socket_error_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_sock_notify failed");
	}
	res = knet_host_enable_status_change_notify(instance->knet_handle, instance, host_change_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_host_enable_status_change_notify failed");
	}
	res = knet_handle_enable_pmtud_notify(instance->knet_handle, instance, pmtu_change_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_pmtud_notify failed");
	}

	/* Get an fd into knet */
	instance->knet_fd = 0;
	res = knet_handle_add_datafd(instance->knet_handle, &instance->knet_fd, &channel);
	if (res) {
		knet_log_printf(LOG_DEBUG, "knet_handle_add_datafd failed: %s", strerror(errno));
		return -1;
	}

	/* Enable crypto if requested */
	if (strcmp(instance->totem_config->crypto_cipher_type, "none") != 0) {
		struct knet_handle_crypto_cfg crypto_cfg;

		strcpy(crypto_cfg.crypto_model, "nss");
		strcpy(crypto_cfg.crypto_cipher_type, instance->totem_config->crypto_cipher_type);
		strcpy(crypto_cfg.crypto_hash_type, instance->totem_config->crypto_hash_type);
		memcpy(crypto_cfg.private_key, instance->totem_config->private_key, instance->totem_config->private_key_len);
		crypto_cfg.private_key_len = instance->totem_config->private_key_len;

		res = knet_handle_crypto(instance->knet_handle, &crypto_cfg);
		if (res == -1) {
			knet_log_printf(LOG_ERR, "knet_handle_crypto failed: %s", strerror(errno));
			return -1;
		}
		if (res == -2) {
			knet_log_printf(LOG_ERR, "knet_handle_crypto failed: -2");
			return -1;
		}
		knet_log_printf(LOG_INFO, "kronosnet crypto initialized: %s/%s", crypto_cfg.crypto_cipher_type, crypto_cfg.crypto_hash_type);
	}
	knet_handle_setfwd(instance->knet_handle, 1);

	instance->link_mode = KNET_LINK_POLICY_PASSIVE;
	if (strcmp(instance->totem_config->link_mode, "active")==0) {
		instance->link_mode = KNET_LINK_POLICY_ACTIVE;
	}
	if (strcmp(instance->totem_config->link_mode, "rr")==0) {
		instance->link_mode = KNET_LINK_POLICY_RR;
	}

	for (i=0; i<INTERFACE_MAX; i++) {
		instance->link_status[i] = malloc(CFG_INTERFACE_STATUS_MAX_LEN);
		if (!instance->link_status[i]) {
			return -1;
		}
	}

	qb_loop_poll_add (instance->poll_handle,
		QB_LOOP_MED,
		instance->logpipes[0],
		POLLIN, instance, log_deliver_fn);

	qb_loop_poll_add (instance->poll_handle,
		QB_LOOP_HIGH,
		instance->knet_fd,
		POLLIN, instance, data_deliver_fn);

	/*
	 * Upper layer isn't ready to receive message because it hasn't
	 * initialized yet.  Add short timer to check the interfaces.
	 */
	qb_loop_timer_add (instance->poll_handle,
		QB_LOOP_MED,
		100*QB_TIME_NS_IN_MSEC,
		(void *)instance,
		timer_function_netif_check_timeout,
		&instance->timer_netif_check_timeout);

	totemknet_start_merge_detect_timeout(instance);

	/* Start listening for config changes */
	totemknet_add_config_notifications(instance);

	knet_log_printf (LOGSYS_LEVEL_INFO, "totemknet initialized");
	*knet_context = instance;
	return (0);
}
Example #4
0
int main (int argc, char **argv, char **envp)
{
	const char *error_string;
	struct totem_config totem_config;
	int res, ch;
	int background, setprio;
	struct stat stat_out;
	char corosync_lib_dir[PATH_MAX];
	enum e_corosync_done flock_err;
	uint64_t totem_config_warnings;
	struct scheduler_pause_timeout_data scheduler_pause_timeout_data;

	/* default configuration
	 */
	background = 1;
	setprio = 0;

	while ((ch = getopt (argc, argv, "fprv")) != EOF) {

		switch (ch) {
			case 'f':
				background = 0;
				break;
			case 'p':
				break;
			case 'r':
				setprio = 1;
				break;
			case 'v':
				printf ("Corosync Cluster Engine, version '%s'\n", VERSION);
				printf ("Copyright (c) 2006-2009 Red Hat, Inc.\n");
				return EXIT_SUCCESS;

				break;
			default:
				fprintf(stderr, \
					"usage:\n"\
					"        -f     : Start application in foreground.\n"\
					"        -p     : Does nothing.    \n"\
					"        -r     : Set round robin realtime scheduling \n"\
					"        -v     : Display version and SVN revision of Corosync and exit.\n");
				return EXIT_FAILURE;
		}
	}

	/*
	 * Set round robin realtime scheduling with priority 99
	 * Lock all memory to avoid page faults which may interrupt
	 * application healthchecking
	 */
	if (setprio) {
		corosync_setscheduler ();
	}

	corosync_mlockall ();

	/*
	 * Other signals are registered later via qb_loop_signal_add
	 */
	(void)signal (SIGSEGV, sigsegv_handler);
	(void)signal (SIGABRT, sigabrt_handler);
#if MSG_NOSIGNAL != 0
	(void)signal (SIGPIPE, SIG_IGN);
#endif

	if (icmap_init() != CS_OK) {
		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't initialize configuration component.");
		corosync_exit_error (COROSYNC_DONE_ICMAP);
	}
	set_icmap_ro_keys_flag();

	/*
	 * Initialize the corosync_api_v1 definition
	 */
	api = apidef_get ();

	res = coroparse_configparse(icmap_get_global_map(), &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	res = corosync_log_config_read (&error_string);
	if (res == -1) {
		/*
		 * if we are here, we _must_ flush the logsys queue
		 * and try to inform that we couldn't read the config.
		 * this is a desperate attempt before certain death
		 * and there is no guarantee that we can print to stderr
		 * nor that logsys is sending the messages where we expect.
		 */
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		fprintf(stderr, "%s", error_string);
		syslog (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_LOGCONFIGREAD);
	}

	log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Cluster Engine ('%s'): started and ready to provide service.", VERSION);
	log_printf (LOGSYS_LEVEL_INFO, "Corosync built-in features:" PACKAGE_FEATURES "");

	/*
	 * Make sure required directory is present
	 */
	sprintf (corosync_lib_dir, "%s/lib/corosync", LOCALSTATEDIR);
	res = stat (corosync_lib_dir, &stat_out);
	if ((res == -1) || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
		log_printf (LOGSYS_LEVEL_ERROR, "Required directory not present %s.  Please create it.", corosync_lib_dir);
		corosync_exit_error (COROSYNC_DONE_DIR_NOT_PRESENT);
	}

	res = totem_config_read (&totem_config, &error_string, &totem_config_warnings);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_MEMBERS_IGNORED) {
		log_printf (LOGSYS_LEVEL_WARNING, "member section is used together with nodelist. Members ignored.");
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_MEMBERS_DEPRECATED) {
		log_printf (LOGSYS_LEVEL_WARNING, "member section is deprecated.");
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_TOTEM_NODEID_IGNORED) {
		log_printf (LOGSYS_LEVEL_WARNING, "nodeid appears both in totem section and nodelist. Nodelist one is used.");
	}

	if (totem_config_warnings != 0) {
		log_printf (LOGSYS_LEVEL_WARNING, "Please migrate config file to nodelist.");
	}

	res = totem_config_keyread (&totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	res = totem_config_validate (&totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	ip_version = totem_config.ip_version;

	totem_config.totem_logging_configuration = totem_logging_configuration;
	totem_config.totem_logging_configuration.log_subsys_id = _logsys_subsys_create("TOTEM", "totem,"
			"totemmrp.c,totemrrp.c,totemip.c,totemconfig.c,totemcrypto.c,totemsrp.c,"
			"totempg.c,totemiba.c,totemudp.c,totemudpu.c,totemnet.c");

	totem_config.totem_logging_configuration.log_level_security = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_error = LOGSYS_LEVEL_ERROR;
	totem_config.totem_logging_configuration.log_level_warning = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_notice = LOGSYS_LEVEL_NOTICE;
	totem_config.totem_logging_configuration.log_level_debug = LOGSYS_LEVEL_DEBUG;
	totem_config.totem_logging_configuration.log_level_trace = LOGSYS_LEVEL_TRACE;
	totem_config.totem_logging_configuration.log_printf = _logsys_log_printf;
	logsys_config_apply();

	/*
	 * Now we are fully initialized.
	 */
	if (background) {
		corosync_tty_detach ();
	}

	corosync_poll_handle = qb_loop_create ();

	memset(&scheduler_pause_timeout_data, 0, sizeof(scheduler_pause_timeout_data));
	scheduler_pause_timeout_data.totem_config = &totem_config;
	timer_function_scheduler_timeout (&scheduler_pause_timeout_data);

	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_LOW,
		SIGUSR2, NULL, sig_diag_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGINT, NULL, sig_exit_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGQUIT, NULL, sig_exit_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGTERM, NULL, sig_exit_handler, NULL);

	if (logsys_thread_start() != 0) {
		log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize log thread");
		corosync_exit_error (COROSYNC_DONE_LOGCONFIGREAD);
	}

	if ((flock_err = corosync_flock (corosync_lock_file, getpid ())) != COROSYNC_DONE_EXIT) {
		corosync_exit_error (flock_err);
	}

	/*
	 * if totempg_initialize doesn't have root priveleges, it cannot
	 * bind to a specific interface.  This only matters if
	 * there is more then one interface in a system, so
	 * in this case, only a warning is printed
	 */
	/*
	 * Join multicast group and setup delivery
	 *  and configuration change functions
	 */
	totempg_initialize (
		corosync_poll_handle,
		&totem_config);

	totempg_service_ready_register (
		main_service_ready);

	totempg_groups_initialize (
		&corosync_group_handle,
		deliver_fn,
		confchg_fn);

	totempg_groups_join (
		corosync_group_handle,
		&corosync_group,
		1);

	/*
	 * Drop root privleges to user 'corosync'
	 * TODO: Don't really need full root capabilities;
	 *       needed capabilities are:
	 * CAP_NET_RAW (bindtodevice)
	 * CAP_SYS_NICE (setscheduler)
	 * CAP_IPC_LOCK (mlockall)
	 */
	priv_drop ();

	schedwrk_init (
		serialize_lock,
		serialize_unlock);

	/*
	 * Start main processing loop
	 */
	qb_loop_run (corosync_poll_handle);

	/*
	 * Exit was requested
	 */
	totempg_finalize ();

	/*
	 * free the loop resources
	 */
	qb_loop_destroy (corosync_poll_handle);

	/*
	 * free up the icmap 
	 */

	/*
	 * Remove pid lock file
	 */
	unlink (corosync_lock_file);

	corosync_exit_error (COROSYNC_DONE_EXIT);

	return EXIT_SUCCESS;
}
Example #5
0
int _logsys_system_setup(
	const char *mainsystem,
	unsigned int mode,
	int syslog_facility,
	int syslog_priority)
{
	int i;
	int32_t fidx;
	char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];

	if ((mainsystem == NULL) ||
	    (strlen(mainsystem) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
		return -1;
	}

	/*
	 * Setup libqb as a subsys
	 */
	i = _logsys_subsys_create ("QB", "array.c,log.c,log_syslog.c,log_blackbox.c,log_format.c,"
		"log_file.c,log_dcs.c,log_thread.c,ipc_shm.c,ipcs.c,ipc_us.c,loop.c,"
		"loop_poll_epoll.c,loop_job.c,loop_poll_poll.c,loop_poll_kqueue.c,"
		"loop_timerlist.c,loop_poll.c,ringbuffer.c,ringbuffer_helper.c,trie.c,"
		"map.c,skiplist.c,rpl_sem.c,hdb.c,unix.c,hashtable.c,strlcpy.c,ipc_socket.c,"
		"strchrnul.c,ipc_setup.c,strlcat.c");
	if (i < 0) {
		return -1;
	}

	/*
	 * name clash
	 * _logsys_subsys_filename_add (i, "util.c");
	 */

	/*
	 * This file (logsys.c) is not exactly QB. We need tag for logsys.c if flightrecorder init
	 * fails, and QB seems to be closest.
	 */
	_logsys_subsys_filename_add (i, "logsys.c");

	i = LOGSYS_MAX_SUBSYS_COUNT;

	pthread_mutex_lock (&logsys_config_mutex);

	snprintf(logsys_loggers[i].subsys,
		 LOGSYS_MAX_SUBSYS_NAMELEN,
		"%s", mainsystem);

	logsys_loggers[i].mode = mode;
	logsys_loggers[i].debug = LOGSYS_DEBUG_OFF;
	logsys_loggers[i].file_idx = 0;
	logsys_loggers[i].logfile_priority = syslog_priority;
	logsys_loggers[i].syslog_priority = syslog_priority;

	qb_log_init(mainsystem, syslog_facility, syslog_priority);
	if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_STDERR) {
		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
	} else {
		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
	}
	if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_SYSLOG) {
		qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
	} else {
		qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
	}
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP, LOG_INFO - LOG_DEBUG);

	qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
	qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, IPC_LOGSYS_SIZE);
	qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);

	/*
	 * Blackbox is disabled at the init and enabled later based
	 * on config (logging.blackbox) value.
	 */
	qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);

	if (logsys_format_set(NULL) == -1) {
		return -1;
	}

	qb_log_tags_stringify_fn_set(_logsys_tags_stringify);

	logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
	logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;

	for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
		if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
		    (logsys_loggers[i].init_status ==
		     LOGSYS_LOGGER_NEEDS_INIT)) {
			fidx = logsys_loggers[i].file_idx;
			strncpy (tempsubsys, logsys_loggers[i].subsys,
				 sizeof (tempsubsys));
			tempsubsys[sizeof (tempsubsys) - 1] = '\0';
			logsys_subsys_init(tempsubsys, i);
			logsys_loggers[i].file_idx = fidx;
			_logsys_config_mode_set_unlocked(i, logsys_loggers[i].mode);
			_logsys_config_apply_per_subsys(i);
		}
	}

	pthread_mutex_unlock (&logsys_config_mutex);

	return (0);
}
Example #6
0
int main (int argc, char **argv, char **envp)
{
	const char *error_string;
	struct totem_config totem_config;
	int res, ch;
	int background, sched_rr, prio, testonly, move_to_root_cgroup;
	struct stat stat_out;
	enum e_corosync_done flock_err;
	uint64_t totem_config_warnings;
	struct scheduler_pause_timeout_data scheduler_pause_timeout_data;
	long int tmpli;
	char *ep;

	/* default configuration
	 */
	background = 1;
	sched_rr = 1;
	prio = 0;
	testonly = 0;
	move_to_root_cgroup = 1;

	while ((ch = getopt (argc, argv, "fP:pRrtv")) != EOF) {

		switch (ch) {
			case 'f':
				background = 0;
				break;
			case 'p':
				sched_rr = 0;
				break;
			case 'P':
				if (strcmp(optarg, "max") == 0) {
					prio = INT_MIN;
				} else if (strcmp(optarg, "min") == 0) {
					prio = INT_MAX;
				} else {
					errno = 0;

					tmpli = strtol(optarg, &ep, 10);
					if (errno != 0 || *ep != '\0' || tmpli > INT_MAX || tmpli < INT_MIN) {
						fprintf(stderr, "Priority value %s is invalid", optarg);
						logsys_system_fini();
						return EXIT_FAILURE;
					}

					prio = tmpli;
				}
				break;
			case 'R':
				move_to_root_cgroup = 0;
				break;
			case 'r':
				sched_rr = 1;
				break;
			case 't':
				testonly = 1;
				break;
			case 'v':
				printf ("Corosync Cluster Engine, version '%s'\n", VERSION);
				printf ("Copyright (c) 2006-2009 Red Hat, Inc.\n");
				logsys_system_fini();
				return EXIT_SUCCESS;

				break;
			default:
				fprintf(stderr, \
					"usage:\n"\
					"        -f     : Start application in foreground.\n"\
					"        -p     : Do not set realtime scheduling.\n"\
					"        -r     : Set round robin realtime scheduling (default).\n"\
					"        -R     : Do not try move corosync to root cpu cgroup (valid when built with libcgroup)\n" \
					"        -P num : Set priority of process (no effect when -r is used)\n"\
					"        -t     : Test configuration and exit.\n"\
					"        -v     : Display version and SVN revision of Corosync and exit.\n");
				logsys_system_fini();
				return EXIT_FAILURE;
		}
	}


	/*
	 * Other signals are registered later via qb_loop_signal_add
	 */
	(void)signal (SIGSEGV, sigsegv_handler);
	(void)signal (SIGABRT, sigsegv_handler);
#if MSG_NOSIGNAL != 0
	(void)signal (SIGPIPE, SIG_IGN);
#endif

	if (icmap_init() != CS_OK) {
		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't initialize configuration component.");
		corosync_exit_error (COROSYNC_DONE_ICMAP);
	}
	set_icmap_ro_keys_flag();

	/*
	 * Initialize the corosync_api_v1 definition
	 */
	api = apidef_get ();

	res = coroparse_configparse(icmap_get_global_map(), &error_string);
	if (res == -1) {
		/*
		 * Logsys can't log properly at this early stage, and we need to get this message out
		 *
		 */
		fprintf (stderr, "%s\n", error_string);
		syslog (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	if (stats_map_init(api) != CS_OK) {
		fprintf (stderr, "Corosync Executive couldn't initialize statistics component.\n");
		syslog (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't initialize statistics component.");
		corosync_exit_error (COROSYNC_DONE_STATS);
	}

	res = corosync_log_config_read (&error_string);
	if (res == -1) {
		/*
		 * if we are here, we _must_ flush the logsys queue
		 * and try to inform that we couldn't read the config.
		 * this is a desperate attempt before certain death
		 * and there is no guarantee that we can print to stderr
		 * nor that logsys is sending the messages where we expect.
		 */
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		fprintf(stderr, "%s", error_string);
		syslog (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_LOGCONFIGREAD);
	}

	if (!testonly) {
		log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Cluster Engine ('%s'): started and ready to provide service.", VERSION);
		log_printf (LOGSYS_LEVEL_INFO, "Corosync built-in features:" PACKAGE_FEATURES "");
	}

	/*
	 * Make sure required directory is present
	 */
	res = stat (get_run_dir(), &stat_out);
	if ((res == -1) || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
		log_printf (LOGSYS_LEVEL_ERROR, "Required directory not present %s.  Please create it.", get_run_dir());
		corosync_exit_error (COROSYNC_DONE_DIR_NOT_PRESENT);
	}

	res = chdir(get_run_dir());
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "Cannot chdir to run directory %s.  "
		    "Please make sure it has correct context and rights.", get_run_dir());
		corosync_exit_error (COROSYNC_DONE_DIR_NOT_PRESENT);
	}

	res = totem_config_read (&totem_config, &error_string, &totem_config_warnings);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_MEMBERS_IGNORED) {
		log_printf (LOGSYS_LEVEL_WARNING, "member section is used together with nodelist. Members ignored.");
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_MEMBERS_DEPRECATED) {
		log_printf (LOGSYS_LEVEL_WARNING, "member section is deprecated.");
	}

	if (totem_config_warnings & TOTEM_CONFIG_WARNING_TOTEM_NODEID_IGNORED) {
		log_printf (LOGSYS_LEVEL_WARNING, "nodeid appears both in totem section and nodelist. Nodelist one is used.");
	}

	if (totem_config_warnings & TOTEM_CONFIG_BINDNETADDR_NODELIST_SET) {
		log_printf (LOGSYS_LEVEL_WARNING, "interface section bindnetaddr is used together with nodelist. "
		    "Nodelist one is going to be used.");
	}

	if (totem_config_warnings != 0) {
		log_printf (LOGSYS_LEVEL_WARNING, "Please migrate config file to nodelist.");
	}

	res = totem_config_keyread (&totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	res = totem_config_validate (&totem_config, &error_string);
	if (res == -1) {
		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
	}

	if (testonly) {
		corosync_exit_error (COROSYNC_DONE_EXIT);
	}


	/*
	 * Try to move corosync into root cpu cgroup. Failure is not fatal and
	 * error is deliberately ignored.
	 */
	if (move_to_root_cgroup) {
		(void)corosync_move_to_root_cgroup();
	}

	/*
	 * Set round robin realtime scheduling with priority 99
	 */
	if (sched_rr) {
		if (corosync_set_rr_scheduler () != 0) {
			prio = INT_MIN;
		} else {
			prio = 0;
		}
	}

	if (prio != 0) {
		if (setpriority(PRIO_PGRP, 0, prio) != 0) {
			LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING,
				"Could not set priority %d", prio);
		}
	}

	ip_version = totem_config.ip_version;

	totem_config.totem_memb_ring_id_create_or_load = corosync_ring_id_create_or_load;
	totem_config.totem_memb_ring_id_store = corosync_ring_id_store;

	totem_config.totem_logging_configuration = totem_logging_configuration;
	totem_config.totem_logging_configuration.log_subsys_id = _logsys_subsys_create("TOTEM", "totem,"
			"totemip.c,totemconfig.c,totemcrypto.c,totemsrp.c,"
			"totempg.c,totemudp.c,totemudpu.c,totemnet.c,totemknet.c");

	totem_config.totem_logging_configuration.log_level_security = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_error = LOGSYS_LEVEL_ERROR;
	totem_config.totem_logging_configuration.log_level_warning = LOGSYS_LEVEL_WARNING;
	totem_config.totem_logging_configuration.log_level_notice = LOGSYS_LEVEL_NOTICE;
	totem_config.totem_logging_configuration.log_level_debug = LOGSYS_LEVEL_DEBUG;
	totem_config.totem_logging_configuration.log_level_trace = LOGSYS_LEVEL_TRACE;
	totem_config.totem_logging_configuration.log_printf = _logsys_log_printf;

	logsys_config_apply();

	/*
	 * Now we are fully initialized.
	 */
	if (background) {
		logsys_blackbox_prefork();

		corosync_tty_detach ();

		logsys_blackbox_postfork();

		log_printf (LOGSYS_LEVEL_DEBUG, "Corosync TTY detached");
	}

	/*
	 * Lock all memory to avoid page faults which may interrupt
	 * application healthchecking
	 */
	corosync_mlockall ();

	corosync_poll_handle = qb_loop_create ();

	memset(&scheduler_pause_timeout_data, 0, sizeof(scheduler_pause_timeout_data));
	scheduler_pause_timeout_data.totem_config = &totem_config;
	timer_function_scheduler_timeout (&scheduler_pause_timeout_data);

	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_LOW,
		SIGUSR2, NULL, sig_diag_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGINT, NULL, sig_exit_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGQUIT, NULL, sig_exit_handler, NULL);
	qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH,
		SIGTERM, NULL, sig_exit_handler, NULL);

	if (logsys_thread_start() != 0) {
		log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize log thread");
		corosync_exit_error (COROSYNC_DONE_LOGCONFIGREAD);
	}

	if ((flock_err = corosync_flock (corosync_lock_file, getpid ())) != COROSYNC_DONE_EXIT) {
		corosync_exit_error (flock_err);
	}

	/*
	 * if totempg_initialize doesn't have root priveleges, it cannot
	 * bind to a specific interface.  This only matters if
	 * there is more then one interface in a system, so
	 * in this case, only a warning is printed
	 */
	/*
	 * Join multicast group and setup delivery
	 *  and configuration change functions
	 */
	if (totempg_initialize (
		corosync_poll_handle,
		&totem_config) != 0) {

		log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize TOTEM layer");
		corosync_exit_error (COROSYNC_DONE_FATAL_ERR);
	}

	totempg_service_ready_register (
		main_service_ready);

	totempg_groups_initialize (
		&corosync_group_handle,
		deliver_fn,
		confchg_fn);

	totempg_groups_join (
		corosync_group_handle,
		&corosync_group,
		1);

	/*
	 * Drop root privleges to user 'corosync'
	 * TODO: Don't really need full root capabilities;
	 *       needed capabilities are:
	 * CAP_NET_RAW (bindtodevice)
	 * CAP_SYS_NICE (setscheduler)
	 * CAP_IPC_LOCK (mlockall)
	 */
	priv_drop ();

	schedwrk_init (
		serialize_lock,
		serialize_unlock);

	/*
	 * Start main processing loop
	 */
	qb_loop_run (corosync_poll_handle);

	/*
	 * Exit was requested
	 */
	totempg_finalize ();

	/*
	 * free the loop resources
	 */
	qb_loop_destroy (corosync_poll_handle);

	/*
	 * free up the icmap 
	 */

	/*
	 * Remove pid lock file
	 */
	unlink (corosync_lock_file);

	corosync_exit_error (COROSYNC_DONE_EXIT);

	return EXIT_SUCCESS;
}