/** * Spawns an instance of the FM component. * * @param instance Instance number the component belongs to * @param component Integer representation of the component * (1 = SM, 2 = FE) * @return int PID spawned or -1 if an error has occurred */ int spawn(const unsigned int instance, const int component){ sigset_t mask; int *pids; int pid; char prog[32], name[32]; if (instance >= FM_MAX_INSTANCES){ fprintf(stderr, "Invalid instance number.\n"); return -1; } if ((pids = componentToPIDArray(component)) == NULL){ fprintf(stderr, "spawn: Invalid component number %d.\n", component); return -1; } if (pids[instance] != 0 && kill(pids[instance], 0) == 0){ fprintf(stderr, "Instance %d of %s is already running.\n", instance, componentToString(component)); return -1; } if (!config.instance[instance].component[component].enabled){ fprintf(stderr, "Instance %d of %s is not enabled. Please enable instance in %s\n", instance, componentToString(component), FM_XML_CONFIG); return -1; } switch(pid = fork()){ case 0: sigemptyset(&mask); sigaddset(&mask,SIGTERM); sigaddset(&mask,SIGCHLD); sigaddset(&mask,SIGHUP); sigprocmask(SIG_UNBLOCK, &mask, NULL); sprintf(prog, "/usr/lib/opa-fm/runtime/%s", componentToExecName(component)); sprintf(name, "%s_%d", componentToExecName(component), instance); execle(prog, prog, "-e", name, NULL, nullEnv); break; case -1: fprintf(stderr, "Failed to start %s for instance %d.\n", componentToString(component), instance); break; default: fprintf(stdout, "Started instance %d of %s.\n", instance, componentToString(component)); if(pid > 0) pids[instance] = pid; break; } return pid; }
/** * Kills instance of FM component * * @param instance Instance number the component belongs to * @param component Integer representation of the component * (1 = SM, 2 = FE) * @return int Returns 0 if process was properly terminated, * otherwise -1 on error. */ int pkill(const unsigned int instance, const int component){ int *pids; int pid; int status; int ret; if(instance >= FM_MAX_INSTANCES){ fprintf(stderr, "Invalid instance number.\n"); return -1; } if((pids = componentToPIDArray(component)) == NULL){ fprintf(stderr, "pkill: Invalid component number %d.\n", component); return -1; } pid = pids[instance]; if(!pid) return 0; if(kill(pid, 0) == 0){ kill(pid, SIGTERM); // Here we send a SIGTERM to the PID specified. sleep(component == SM_COMPONENT ? 3 : 1); // Wait 3 seconds for SM to die from SIGTERM, only 1 sec for FE ret = waitpid((pid_t)pid, &status, WUNTRACED | WNOHANG); // Reap the children if they're already dead. Because zombies are bad, mmkay. if(!ret){ // Checks for insubordinate children kill(pid, SIGKILL); // Order a hit on them sleep(component == SM_COMPONENT ? 3 : 1); // Allow 1-3 seconds for murder ret = waitpid((pid_t)pid, &status, WUNTRACED | WNOHANG); // Reap if(!ret){ // Report all survivors fprintf(stderr, "Failed to kill %s from instance %d\n", componentToString(component), instance); return -1; } } instanceRestarts[instance].components[component].lastUpdate = 0; // Make sure to reset restart timer to prevent manual stop/restart from counting against component fprintf(stdout, "Stopped instance %d of %s.\n", instance, componentToString(component)); } else { fprintf(stderr, "Instance %d of %s not running.\n", instance, componentToString(component)); } pids[instance] = 0; // PID not running or doesn't exist return 0; }
/** * Function to parse values passed through named pipe to the * daemon. * * @param buf Pointer to the string extracted from the named * pipe * * @return int Returns 1 if the daemon recieved a command to * stop. */ int parseInput(char *buf){ char *token; int i, c; struct thread_data *thread = NULL; pthread_t thread_id[FM_MAX_INSTANCES*FM_NUM_COMPONENTS]; token = strtok(buf, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } if(strncmp(token, "sig_chld", 8) == 0){ int i = 0, pid = 0, stat = 0; unsigned int instance = 0, component = 0; while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { for(i = 0; i < FM_MAX_INSTANCES; ++i){ if(smPID[i] == pid){ component = SM_COMPONENT; instance = i; break; } else if (fePID[i] == pid){ component = FE_COMPONENT; instance = i; break; } } if(component == 0){ continue; } fprintf(stderr, "%s component of instance %d has terminated with exit code %d\n", componentToString(component), instance, stat); if(stat == 0 || stat == 1){ //Skip restarting these components if expected (return 0) or user error (return 1) if(stat == 1) fprintf(stderr, "Check opafm.xml config for invalid settings.\n"); return 0; } if(checkRestarts(instance, component)){ //Component has failed too many times doStop = 3; return 0; } if (pkill(instance, component) == 0){ spawn(instance, component); } else { //Failed to kill child. Might be a zombie. doStop = 3; return 0; } } } else if(!strncmp(token, "stop", 4) || !strncmp(token, "sig_term", 8)){ token = strtok(NULL, " "); if(token == NULL) token = "a"; switch(token[0]){ case '0': // Kill both SM and FE for this instance number. doStop = 1; token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); if(i >= FM_MAX_INSTANCES || i < 0){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } for(c = FM_NUM_COMPONENTS - 1; c >= 1; --c){ thread = calloc(1, sizeof(struct thread_data)); if(thread == NULL){ fprintf(stderr, "Failed to allocate thread struct.\n"); return 0; } thread->instance = i; thread->component = c; pthread_create(&thread_id[c], NULL, &kill_thread, thread); } for(c = 1; c < FM_NUM_COMPONENTS; ++c){ pthread_join(thread_id[c], NULL); } break; case '1': // SM and FE are treated the same so this prevents code redundancy case '2': c = atoi((const char*)token); token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); pkill(i, c); break; case 'a': // Kill all running instances. doStop = 1; for(i = 0; i < FM_MAX_INSTANCES; ++i){ for(c = 1; c < FM_NUM_COMPONENTS; ++c){ thread = calloc(1, sizeof(struct thread_data)); if(thread == NULL){ fprintf(stderr, "Failed to allocate thread struct.\n"); return 0; } thread->instance = i; thread->component = c; pthread_create(&thread_id[i*FM_NUM_COMPONENTS+c], NULL, &kill_thread, thread); } } for(i = 0; i < FM_MAX_INSTANCES; ++i){ for(c = 1; c < FM_NUM_COMPONENTS; ++c){ pthread_join(thread_id[i*FM_NUM_COMPONENTS+c], NULL); } } return 1; default: fprintf(stderr, "Unknown component value. (%d)\n", token[0]); } return 0; } if(strncmp(token, "start", 5) == 0){ token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } switch(token[0]){ case '0': token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); if(i > FM_MAX_INSTANCES){ //Adding additional instance check here to avoid duplicate error messages fprintf(stderr, "Received invalid instance number %d. Ignoring.\n", i); return 0; } spawn(i, SM_COMPONENT); spawn(i, FE_COMPONENT); break; case '1': case '2': c = atoi((const char*)token); token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); spawn(i, c); break; default: fprintf(stderr, "Unknown component value.\n"); } } else if(strncmp(token, "sig_hup", 7) == 0){ loadConfig(); updateInstances(); reloadSMs(); } else if(strncmp(token, "restart", 7) == 0){ token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } switch(token[0]){ case '0': token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); if(i > FM_MAX_INSTANCES){ //Adding additional instance check here to avoid duplicate error messages fprintf(stderr, "Received invalid instance number %d. Ignoring.\n", i); return 0; } if(pkill(i, SM_COMPONENT) == 0) spawn(i, SM_COMPONENT); if(pkill(i, FE_COMPONENT) == 0) spawn(i, FE_COMPONENT); break; case '1': case '2': c = atoi((const char*)token); token = strtok(NULL, " "); if(token == NULL){ fprintf(stderr, "Received invalid input. Ignoring.\n"); return 0; } i = atoi((const char*)token); if(pkill(i, c) == 0) spawn(i, c); break; default: fprintf(stderr, "Unknown component value.\n"); } } return 0; }
QXmlStreamWriter& SimpleLoggerRoutingInfo::write(QXmlStreamWriter& writer) const { writer.writeStartElement("SimpleLoggerRoutingInfo"); if (m_name.length() > 0) { XMLUtility::writeElement(writer, "Name", m_name); } XMLUtility::writeElement(writer, "Enabled", XMLUtility::booleanToString(m_enabled)); if (m_levels != nullptr && m_levels->size() > 0) { QMap<MessageCategory, int>::const_iterator i; for (i = m_levels->begin(); i != m_levels->end(); ++i) { XMLUtility::writeElementAttribute(writer, "Level", QString::number(i.value()), "MessageCategory", categoryToString(i.key(), -1)); } } if (m_routing != nullptr && m_routing->size() > 0) { QMap<MessageRouting, bool>::const_iterator i; for (i = m_routing->begin(); i != m_routing->end(); ++i) { XMLUtility::writeElementAttribute(writer, "Routing", XMLUtility::booleanToString(i.value()), "MessageRouting", routingToString(i.key(), -1)); } } if (m_locationRegExp != nullptr) { XMLUtility::write(writer, *m_locationRegExp, "LocationRegEx"); } if (m_messageRegExp != nullptr) { XMLUtility::write(writer, *m_messageRegExp, "MessageRegEx"); } if (m_format.size() > 0) { for (int i=0; i<m_format.size(); ++i) { const QPair<MessageComponent, QString>& comp = m_format.at(i); XMLUtility::writeElementAttribute(writer, "Format", comp.second, "MessageComponent", componentToString(comp.first, comp.second.length())); } } writer.writeEndElement(); return writer; }