in common/recipes-core/rackmon/rackmon/rackmond.c [1902:2076]
int main(int argc, char** argv) {
int error = 0;
int sock = -1;
pthread_t monitoring_tid;
sigset_t new_mask, old_mask;
struct sockaddr_un client;
if (single_instance_lock(DAEMON_NAME) < 0) {
fprintf(stderr, "Another %s instance is running. Exiting!\n",
DAEMON_NAME);
return -1;
}
obmc_log_init(DAEMON_NAME, LOG_INFO, 0);
obmc_log_set_syslog(LOG_CONS, LOG_DAEMON);
if (getenv("RACKMOND_FOREGROUND") == NULL) {
obmc_log_unset_std_stream();
if (daemon(0, 0) < 0)
OBMC_ERROR(errno, "daemon error");
}
#ifdef RACKMON_PROFILING
OBMC_INFO("ticks_per_sec: %ld", sysconf(_SC_CLK_TCK));
#endif /* RACKMON_PROFILING */
if (signal_handler_init() != 0)
return -1;
if (getenv("RACKMOND_TIMEOUT") != NULL) {
rackmond_config.modbus_timeout = atoll(getenv("RACKMOND_TIMEOUT"));
OBMC_INFO("set timeout to RACKMOND_TIMEOUT (%dms)",
rackmond_config.modbus_timeout / 1000);
}
if (getenv("RACKMOND_MIN_DELAY") != NULL) {
rackmond_config.min_delay = atoll(getenv("RACKMOND_MIN_DELAY"));
OBMC_INFO("set mindelay to RACKMOND_MIN_DELAY(%dus)",
rackmond_config.min_delay);
}
verbose = getenv("RACKMOND_VERBOSE") != NULL ? 1 : 0;
if (getenv("RACKMOND_MULTI_PORT") != NULL){
rackmond_config.multi_port = 1;
OBMC_INFO("set RACKMOND_MULTI_PORT to %d, for FT4232",
rackmond_config.multi_port);
} else {
rackmond_config.multi_port = 0;
OBMC_INFO("set RACKMOND_MULTI_PORT to %d, for FT232",
rackmond_config.multi_port);
}
if (getenv("RACKMOND_SWAP_ADDR") != NULL){
rackmond_config.swap_addr = 1;
OBMC_INFO("set RACKMOND_SWAP_ADDR to %d, for W400 MP Respin",
rackmond_config.multi_port);
} else {
rackmond_config.swap_addr = 0;
OBMC_INFO("set RACKMOND_SWAP_ADDR to %d.",
rackmond_config.multi_port);
}
if (getenv("RACKMOND_DESIRED_BAUDRATE") != NULL) {
int parsed_baudrate_int = atoi(getenv("RACKMOND_DESIRED_BAUDRATE"));
rackmond_config.desired_baudrate = int_to_baudrate(parsed_baudrate_int);
OBMC_INFO("set desired baudrate value to RACKMOND_DESIRED_BAUDRATE (%d -> %s)",
parsed_baudrate_int,
baud_to_str(rackmond_config.desired_baudrate));
}
if (getenv("RACKMOND_IGNORE_PSUS") != NULL) {
char *ignore_list = strdup(getenv("RACKMOND_IGNORE_PSUS"));
if (ignore_list) {
char *psu_str;
for (psu_str = strtok(ignore_list, ",");
psu_str != NULL;
psu_str = strtok(NULL, ",")) {
unsigned int psu_addr = strtoul(psu_str, 0, 16);
int rack, shelf, psu;
if (!psu_location(psu_addr, &rack, &shelf, &psu)) {
rackmond_config.ignored_psus[rack][shelf][psu] = true;
OBMC_INFO("Ignoring PSU: 0x%x\n", psu_addr);
} else {
OBMC_ERROR(EINVAL, "Unsupported PSU: 0x%x provided to RACKMOND_IGNORE_PSUS\n", psu_addr);
}
}
free(ignore_list);
}
}
OBMC_INFO("rackmon/modbus service starting");
if (rackmon_plat_init() != 0) {
return -1;
}
if (rackmond_config.multi_port) {
if (rs485_device_init(DEFAULT_TTY1, &rackmond_config.rs485[0]) != 0) {
error = -1;
goto exit_rs485;
}
if (rs485_device_init(DEFAULT_TTY2, &rackmond_config.rs485[1]) != 0) {
error = -1;
goto exit_rs485;
}
if (rs485_device_init(DEFAULT_TTY3, &rackmond_config.rs485[2]) != 0) {
error = -1;
goto exit_rs485;
}
} else {
if (rs485_device_init(DEFAULT_TTY, &rackmond_config.rs485[0]) != 0) {
error = -1;
goto exit_rs485;
}
}
error = pthread_create(&monitoring_tid, NULL, monitoring_loop, NULL);
if (error != 0) {
OBMC_ERROR(error, "failed to create monitor loop thread");
error = -1;
goto exit_thread;
}
sock = user_socket_init(RACKMON_IPC_SOCKET);
if (sock < 0) {
goto exit_sock;
}
OBMC_INFO("rackmon is listening to user connections");
/*
* SIGINT and SIGTERM are blocked before testing "should_exit", and
* they will be unblocked in pselect(): this is to prevent the race
* when the signals were delivered right after testing "should_exit"
* but before calling pselect().
*/
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGINT);
sigaddset(&new_mask, SIGTERM);
sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
while (!should_exit) {
int ret;
fd_set rfds;
socklen_t clisocklen = sizeof(struct sockaddr_un);
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
ret = pselect(sock + 1, &rfds, NULL, NULL, NULL, &old_mask);
if (ret > 0 && FD_ISSET(sock, &rfds)) {
int clisock = accept(sock, (struct sockaddr*)&client, &clisocklen);
if (clisock < 0) {
OBMC_ERROR(errno, "failed to accept new connection");
continue;
}
handle_connection(clisock);
close(clisock);
}
}
close(sock); /* ignore errors */
if (reset_psu_baudrate() != 0)
error = -1;
exit_sock:
pthread_cancel(monitoring_tid); /* ignore errors */
pthread_join(monitoring_tid, NULL); /* ignore errors */
exit_thread:
if (rackmond_config.multi_port) {
rs485_device_cleanup(&rackmond_config.rs485[0]);
rs485_device_cleanup(&rackmond_config.rs485[1]);
rs485_device_cleanup(&rackmond_config.rs485[2]);
} else {
rs485_device_cleanup(&rackmond_config.rs485[0]);
}
exit_rs485:
rackmon_plat_cleanup();
OBMC_INFO("rackmon is terminated, exit code: %d", error);
return error;
}