Skip to content

Commit

Permalink
tools: acrn-crashlog: event handler thread for acrnprobe
Browse files Browse the repository at this point in the history
Event handler is the thread to handle events detected by channel.
It's awakened by a enqueued event.

Signed-off-by: Liu Xinwu <xinwu.liu@intel.com>
Reviewed-by: Zhang Yanmin <yanmin.zhang@intel.com>
Reviewed-by: Liu Chuansheng <chuansheng.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
Acked-by: Eddie Dong <Eddie.dong@intel.com>
  • Loading branch information
lauxinw authored and lijinxia committed May 23, 2018
1 parent 9caa5d7 commit 384c195
Showing 1 changed file with 178 additions and 0 deletions.
178 changes: 178 additions & 0 deletions tools/acrn-crashlog/acrnprobe/event_handler.c
Expand Up @@ -3,9 +3,187 @@
* 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;

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;
}

0 comments on commit 384c195

Please sign in to comment.