I have program that uses the logger. The logger is a shared library with yet one process for output (it uses Linux MQ to send messages from main process to logging process).
In my app I try to listen SIGINT
and SIGPIPE
signals to shut down my server:
/* 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!");
}
}
The problem is when I press Ctrl+C in terminal my app stops to print log messages but two processes still work.
Where could the problem be?
P.S. If you need more details just write in comments which, I'll add.
ADDED
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);
}
}