191 lines
3.8 KiB
C
191 lines
3.8 KiB
C
/*
|
|
* Copyright (C) 2018 Intel Corporation
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include "event_queue.h"
|
|
#include "load_conf.h"
|
|
#include "channels.h"
|
|
#include "fsutils.h"
|
|
#include "log_sys.h"
|
|
#include "event_handler.h"
|
|
|
|
/* Watchdog timeout in second*/
|
|
#define WDT_TIMEOUT 300
|
|
|
|
static struct event_t *last_e;
|
|
static int event_processing;
|
|
|
|
/**
|
|
* Handle watchdog expire.
|
|
*
|
|
* @param signal Signal which triggered this function.
|
|
*/
|
|
static void wdt_timeout(int signal)
|
|
{
|
|
struct event_t *e;
|
|
struct crash_t *crash;
|
|
struct info_t *info;
|
|
int count;
|
|
|
|
if (signal == SIGALRM) {
|
|
LOGE("haven't received heart beat(%ds) for %ds, killing self\n",
|
|
HEART_BEAT, WDT_TIMEOUT);
|
|
|
|
if (event_processing) {
|
|
LOGE("event (%d, %s) processing...\n",
|
|
last_e->event_type, last_e->path);
|
|
free(last_e);
|
|
}
|
|
|
|
count = events_count();
|
|
LOGE("total %d unhandled events :\n", count);
|
|
|
|
while (count-- && (e = event_dequeue())) {
|
|
switch (e->event_type) {
|
|
case CRASH:
|
|
crash = (struct crash_t *)e->private;
|
|
LOGE("CRASH (%s, %s)\n", (char *)crash->name,
|
|
e->path);
|
|
break;
|
|
case INFO:
|
|
info = (struct info_t *)e->private;
|
|
LOGE("INFO (%s)\n", (char *)info->name);
|
|
break;
|
|
case UPTIME:
|
|
LOGE("UPTIME\n");
|
|
break;
|
|
case HEART_BEAT:
|
|
LOGE("HEART_BEAT\n");
|
|
break;
|
|
case REBOOT:
|
|
LOGE("REBOOT\n");
|
|
break;
|
|
default:
|
|
LOGE("error event type %d\n", e->event_type);
|
|
}
|
|
free(e);
|
|
}
|
|
|
|
raise(SIGKILL);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fed watchdog.
|
|
*
|
|
* @param timeout in second When the watchdog expire next time.
|
|
*/
|
|
static void watchdog_fed(int timeout)
|
|
{
|
|
struct itimerval new_value;
|
|
int ret;
|
|
|
|
memset(&new_value, 0, sizeof(new_value));
|
|
|
|
new_value.it_value.tv_sec = timeout;
|
|
ret = setitimer(ITIMER_REAL, &new_value, NULL);
|
|
if (ret < 0) {
|
|
LOGE("setitimer failed, error (%s)\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize watchdog. This watchdog is used to monitor event handler.
|
|
*
|
|
* @param timeout in second When the watchdog expire next time.
|
|
*/
|
|
static void watchdog_init(int timeout)
|
|
{
|
|
struct itimerval new_value;
|
|
int ret;
|
|
sighandler_t ohdlr;
|
|
|
|
ohdlr = signal(SIGALRM, wdt_timeout);
|
|
if (ohdlr == SIG_ERR) {
|
|
LOGE("signal failed, error (%s)\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
memset(&new_value, 0, sizeof(new_value));
|
|
|
|
new_value.it_value.tv_sec = timeout;
|
|
ret = setitimer(ITIMER_REAL, &new_value, NULL);
|
|
if (ret < 0) {
|
|
LOGE("setitimer failed, error (%s)\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process each event in event queue.
|
|
* Note that currently event handler is single threaded.
|
|
*/
|
|
static void *event_handle(void *unused __attribute__((unused)))
|
|
{
|
|
int id;
|
|
struct sender_t *sender;
|
|
struct event_t *e;
|
|
|
|
while ((e = event_dequeue())) {
|
|
/* here we only handle internal event */
|
|
if (e->event_type == HEART_BEAT) {
|
|
watchdog_fed(WDT_TIMEOUT);
|
|
free(e);
|
|
continue;
|
|
}
|
|
|
|
/* last_e is allocated for debug purpose, the information
|
|
* will be dumped if watchdog expire.
|
|
*/
|
|
last_e = malloc(sizeof(*e) + e->len);
|
|
if (last_e == NULL) {
|
|
LOGE("malloc failed, error (%s)\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
event_processing = 1;
|
|
memcpy(last_e, e, sizeof(*e) + e->len);
|
|
|
|
for_each_sender(id, sender, conf) {
|
|
if (!sender)
|
|
continue;
|
|
|
|
if (sender->send)
|
|
sender->send(e);
|
|
}
|
|
|
|
if ((e->dir))
|
|
free(e->dir);
|
|
free(e);
|
|
event_processing = 0;
|
|
free(last_e);
|
|
}
|
|
|
|
LOGE("something goes error, %s exit\n", __func__);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Initialize event handler.
|
|
*/
|
|
int init_event_handler(void)
|
|
{
|
|
int ret;
|
|
pthread_t pid;
|
|
|
|
watchdog_init(WDT_TIMEOUT);
|
|
ret = create_detached_thread(&pid, &event_handle, NULL);
|
|
if (ret) {
|
|
LOGE("create event handler failed (%s)\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|