我有使用记录仪的程序。记录器是一个共享库,具有一个用于输出的进程(它使用Linux MQ将消息从主进程发送到日志进程)。
在我的应用中,我尝试监听SIGINT
和SIGPIPE
信号以关闭服务器:
/* Releases all captured resources and shuts down server */
void shutdown_server(int status) {
LOG_I("Shutting down server...");
close(srv_sock);
settings_destroy(&settings);
LOG_I("Success!");
shutdown_log();
exit(status);
}
/* Handles signals */
void handle_signal_action(int sig_number)
{
if (sig_number == SIGINT) {
LOG_D("SIGINT was catched!\n");
shutdown_server(EXIT_SUCCESS);
} else if (sig_number == SIGPIPE) {
LOG_D("SIGPIPE was catched!\n");
shutdown_server(EXIT_SUCCESS);
}
}
/** Subscribes to events when thread was terminated or no reader of the pipe **/
int setup_signals(void (*handler)(int))
{
struct sigaction sa;
sa.sa_handler = handler;
if (sigaction(SIGINT, &sa, 0) != 0) {
LOG_E("Can't subscribe to SIGINT");
return -1;
}
if (sigaction(SIGPIPE, &sa, 0) != 0) {
LOG_E("Can't subscribe to SIGPIPE");
return -1;
}
return 0;
}
/* Entry point */
int main(int argc, char **argv) {
if (setup_signals(handle_signal_action)) {
LOG_F("Can't setup signals");
return -1;
}
if (init_log()) {
printf("Can't initialize logger.\n");
return -1;
}
if (settings_init(&settings, argc, argv)) {
LOG_F("Can't load configuration");
exit(EXIT_FAILURE);
}
settings_log(&settings);
if (socket_init(&srv_sock, settings.address, settings.port)) {
LOG_F("Can't initialize socket");
exit(EXIT_FAILURE);
}
while (1) {
LOG_W("Hello, world!");
}
}
问题是,当我在终端中按 Ctrl + C 时,我的应用程序停止打印日志消息,但是两个进程仍然可以工作。
问题出在哪里?
建议。如果您需要更多详细信息,只需在评论中写上,我会添加。
添加
log.c
#include <log.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <unistd.h>
#define STOP_SIG "!>kill"
/* Message */
typedef struct mq_msg {
log_level_t level;
char msg[MAX_MSG_SIZE + 1];
} mq_msg_t;
/* Process ID */
pid_t pid;
/* Current log level */
log_level_t cur_log_lvl;
/* Message queue descriptor */
mqd_t mq;
/* Message queue attributes */
struct mq_attr attr;
/* Current message */
mq_msg_t cur_msg;
/* Initialize message queue listner for the child process */
void init_listener() {
while (1) {
ssize_t len = mq_receive(mq, (char *)&cur_msg, sizeof(cur_msg), NULL);
if (len > 0) {
// Check stop signal
if (strcmp(STOP_SIG, cur_msg.msg) == 0) { exit(EXIT_SUCCESS); }
time_t timestamp;
struct tm *timeinfo;
time(×tamp);
timeinfo = localtime(×tamp);
FILE *f = cur_msg.level < LL_WARNING ? stderr : stdout;
fprintf(f, "[%u][%02d:%02d:%02d] ", (uint32_t)timestamp,
timeinfo->tm_hour,
timeinfo->tm_min,
timeinfo->tm_sec);
fprintf(f, "%s\n", cur_msg.msg);
fflush(f);
usleep(0.725 * 1e6); // TODO: Read about these magic numbers
}
}
}
/* Initializes logger */
bool init_log() {
cur_log_lvl = LL_DEBUG;
// Initialize a message queue
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = sizeof(cur_msg);
attr.mq_curmsgs = 0;
mq = mq_open(MQ_NAME, O_CREAT | O_RDONLY, 0644, &attr);
if (mq == (mqd_t)-1) {
printf("Can't create a message queue\n");
return -1;
}
// Create a logger process
pid = fork();
if (pid == -1) {
printf("Can't create the logger process\n");
return -1;
}
if (pid == 0) {
init_listener(); // Listen the message queue
} else {
mq = mq_open(MQ_NAME, O_WRONLY); // Connect to the message queue
if (mq == (mqd_t)-1) {
printf("Can't connect to the message queue\n");
return -1;
}
}
return 0;
}
void shutdown_log() {
if (mq == (mqd_t)-1) { mq_close(mq); }
if (pid > 0) {
memset(cur_msg.msg, 0, sizeof(cur_msg.msg));
strcpy(cur_msg.msg, STOP_SIG);
mq_send(mq, (const char *)&cur_msg, sizeof(cur_msg), 0);
}
}
/* Destructor */
void __attribute__((destructor)) finish_log() {
shutdown_log();
}
/* Sets log level */
void set_log_level(log_level_t lvl) {
cur_log_lvl = lvl;
}
/* Returns log level */
log_level_t get_log_level() {
return cur_log_lvl;
}
/* Sends log message to the message queue */
void trace(const char *format, ...) {
if (pid != 0) {
cur_msg.level = LL_DEBUG;
va_list args;
va_start(args, format);
vsnprintf(cur_msg.msg, MAX_MSG_SIZE, format, args);
va_end(args);
mq_send(mq, (const char *)&cur_msg, sizeof(cur_msg), 0);
}
}