mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-30 09:12:57 +00:00
tools:acrn-crashlog: separate the detection and collection of vm events
Push the recorded vm events to event_queue, and let senders do the collecting job in the event_handler thread. Tracked-On: #1024 Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com> Reviewed-by: Liu, Xiaojing <xiaojing.liu@intel.com> Acked-by: Chen, Gang <gang.c.chen@intel.com>
This commit is contained in:
parent
84cf7156ae
commit
fa1216325b
@ -130,11 +130,13 @@ static int get_vms_history(const struct sender_t *sender)
|
|||||||
vm->datafs = NULL;
|
vm->datafs = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e2fs_close(vm->datafs);
|
||||||
|
vm->datafs = NULL;
|
||||||
|
|
||||||
if (!size) {
|
if (!size) {
|
||||||
LOGE("empty vm_history from (%s).\n", vm->name);
|
LOGE("empty vm_history from (%s).\n", vm->name);
|
||||||
vm->history_data = NULL;
|
vm->history_data = NULL;
|
||||||
e2fs_close(vm->datafs);
|
|
||||||
vm->datafs = NULL;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +155,15 @@ static int get_vms_history(const struct sender_t *sender)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sync_lines_stage1(struct sender_t *sender)
|
/**
|
||||||
|
* There are 2 stages in vm events sync.
|
||||||
|
* Stage1: detect new vm events and record them into log_vmrecordid file.
|
||||||
|
* Stage2: push the recorded events to event_queue, the senders will do
|
||||||
|
* the corresponding process.
|
||||||
|
*
|
||||||
|
* The design reason is giving UOS some time to get log stored.
|
||||||
|
*/
|
||||||
|
static void detect_new_events(struct sender_t *sender)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
struct vm_t *vm;
|
struct vm_t *vm;
|
||||||
@ -170,7 +180,7 @@ static void sync_lines_stage1(struct sender_t *sender)
|
|||||||
|
|
||||||
data = vm->history_data;
|
data = vm->history_data;
|
||||||
data_size = vm->history_size[sender->id];
|
data_size = vm->history_size[sender->id];
|
||||||
last_key = &vm->last_synced_line_key[sender->id][0];
|
last_key = &vm->last_evt_detected[sender->id][0];
|
||||||
if (*last_key) {
|
if (*last_key) {
|
||||||
start = strstr(data, last_key);
|
start = strstr(data, last_key);
|
||||||
if (start == NULL) {
|
if (start == NULL) {
|
||||||
@ -201,12 +211,12 @@ static void sync_lines_stage1(struct sender_t *sender)
|
|||||||
if (len == -1)
|
if (len == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
start = strchr(line_to_sync, '\n');
|
||||||
if (str_split_ere(line_to_sync, len + 1, vm_format,
|
if (str_split_ere(line_to_sync, len + 1, vm_format,
|
||||||
strlen(vm_format), vmkey,
|
strlen(vm_format), vmkey,
|
||||||
sizeof(vmkey)) != 1) {
|
sizeof(vmkey)) != 1) {
|
||||||
LOGE("get an invalid line from (%s), skip\n",
|
LOGE("get an invalid line from (%s), skip\n",
|
||||||
vm->name);
|
vm->name);
|
||||||
start = strchr(line_to_sync, '\n');
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,12 +225,11 @@ static void sync_lines_stage1(struct sender_t *sender)
|
|||||||
!strcmp(vmkey, "00000000000000000000")) {
|
!strcmp(vmkey, "00000000000000000000")) {
|
||||||
LOGE("invalid key (%s) from (%s)\n",
|
LOGE("invalid key (%s) from (%s)\n",
|
||||||
vmkey, vm->name);
|
vmkey, vm->name);
|
||||||
start = strchr(line_to_sync, '\n');
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("stage1 %s\n", vmkey);
|
LOGD("stage1 %s\n", vmkey);
|
||||||
*(char *)(mempcpy(vm->last_synced_line_key[sender->id],
|
*(char *)(mempcpy(vm->last_evt_detected[sender->id],
|
||||||
vmkey, ANDROID_EVT_KEY_LEN)) = '\0';
|
vmkey, ANDROID_EVT_KEY_LEN)) = '\0';
|
||||||
if (vmrecord_new(&sender->vmrecord, vm->name,
|
if (vmrecord_new(&sender->vmrecord, vm->name,
|
||||||
vmkey) == -1)
|
vmkey) == -1)
|
||||||
@ -239,7 +248,7 @@ static char *next_record(const struct mm_file_t *file, const char *fstart,
|
|||||||
return get_line(tag, tlen, file->begin, file->size, fstart, len);
|
return get_line(tag, tlen, file->begin, file->size, fstart, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sync_lines_stage2(struct sender_t *sender,
|
static void fire_detected_events(struct sender_t *sender,
|
||||||
int (*fn)(const char*, size_t, const struct vm_t *))
|
int (*fn)(const char*, size_t, const struct vm_t *))
|
||||||
{
|
{
|
||||||
struct mm_file_t *recos;
|
struct mm_file_t *recos;
|
||||||
@ -298,10 +307,7 @@ static void sync_lines_stage2(struct sender_t *sender,
|
|||||||
res = fn(hist_line, len + 1, vm);
|
res = fn(hist_line, len + 1, vm);
|
||||||
if (res == VMEVT_HANDLED)
|
if (res == VMEVT_HANDLED)
|
||||||
vmrecord_mark(&sender->vmrecord, vmkey,
|
vmrecord_mark(&sender->vmrecord, vmkey,
|
||||||
strnlen(vmkey, sizeof(vmkey)), SUCCESS);
|
strnlen(vmkey, sizeof(vmkey)), ON_GOING);
|
||||||
else if (res == VMEVT_MISSLOG)
|
|
||||||
vmrecord_mark(&sender->vmrecord, vmkey,
|
|
||||||
strnlen(vmkey, sizeof(vmkey)), MISS_LOG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -310,7 +316,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This function only for initialization */
|
/* This function only for initialization */
|
||||||
static void get_last_line_synced(struct sender_t *sender)
|
static void get_last_evt_detected(struct sender_t *sender)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
struct vm_t *vm;
|
struct vm_t *vm;
|
||||||
@ -322,7 +328,7 @@ static void get_last_line_synced(struct sender_t *sender)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* generally only exec for each vm once */
|
/* generally only exec for each vm once */
|
||||||
if (vm->last_synced_line_key[sender->id][0])
|
if (vm->last_evt_detected[sender->id][0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (vmrecord_last(&sender->vmrecord, vm->name, vm->name_len,
|
if (vmrecord_last(&sender->vmrecord, vm->name, vm->name_len,
|
||||||
@ -335,7 +341,7 @@ static void get_last_line_synced(struct sender_t *sender)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(char *)(mempcpy(vm->last_synced_line_key[sender->id], vmkey,
|
*(char *)(mempcpy(vm->last_evt_detected[sender->id], vmkey,
|
||||||
ANDROID_EVT_KEY_LEN)) = '\0';
|
ANDROID_EVT_KEY_LEN)) = '\0';
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -358,6 +364,11 @@ static char *setup_loop_dev(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
devnr = loopdev_num_get_free();
|
devnr = loopdev_num_get_free();
|
||||||
|
if (devnr < 0) {
|
||||||
|
LOGE("failed to get free loop device\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < devnr; i++) {
|
for (i = 0; i < devnr; i++) {
|
||||||
res = snprintf(loop_dev_tmp, ARRAY_SIZE(loop_dev_tmp),
|
res = snprintf(loop_dev_tmp, ARRAY_SIZE(loop_dev_tmp),
|
||||||
"/dev/loop%d", i);
|
"/dev/loop%d", i);
|
||||||
@ -419,11 +430,15 @@ void refresh_vm_history(struct sender_t *sender,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_last_line_synced(sender);
|
get_last_evt_detected(sender);
|
||||||
get_vms_history(sender);
|
get_vms_history(sender);
|
||||||
|
|
||||||
sync_lines_stage2(sender, fn);
|
/* read events from vmrecords and mark them as ongoing */
|
||||||
sync_lines_stage1(sender);
|
fire_detected_events(sender, fn);
|
||||||
|
|
||||||
|
/* add events to vmrecords */
|
||||||
|
detect_new_events(sender);
|
||||||
|
|
||||||
for_each_vm(id, vm, conf) {
|
for_each_vm(id, vm, conf) {
|
||||||
if (!vm)
|
if (!vm)
|
||||||
continue;
|
continue;
|
||||||
@ -431,9 +446,5 @@ void refresh_vm_history(struct sender_t *sender,
|
|||||||
free(vm->history_data);
|
free(vm->history_data);
|
||||||
vm->history_data = NULL;
|
vm->history_data = NULL;
|
||||||
}
|
}
|
||||||
if (vm->datafs) {
|
|
||||||
e2fs_close(vm->datafs);
|
|
||||||
vm->datafs = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "startupreason.h"
|
#include "startupreason.h"
|
||||||
#include "probeutils.h"
|
#include "probeutils.h"
|
||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
|
#include "android_events.h"
|
||||||
|
|
||||||
#define POLLING_TIMER_SIG 0xCEAC
|
#define POLLING_TIMER_SIG 0xCEAC
|
||||||
|
|
||||||
@ -174,16 +175,40 @@ static struct polling_job_t {
|
|||||||
void (*fn)(union sigval v);
|
void (*fn)(union sigval v);
|
||||||
} vm_job;
|
} vm_job;
|
||||||
|
|
||||||
|
static int create_vm_event(const char *msg, size_t len, const struct vm_t *vm)
|
||||||
|
{
|
||||||
|
struct vm_event_t *vme = malloc(sizeof(*vme));
|
||||||
|
struct event_t *e;
|
||||||
|
|
||||||
|
if (!vme)
|
||||||
|
return VMEVT_DEFER;
|
||||||
|
|
||||||
|
vme->vm_msg = strndup(msg, len);
|
||||||
|
if (!vme->vm_msg) {
|
||||||
|
free(vme);
|
||||||
|
return VMEVT_DEFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
vme->vm_msg_len = len;
|
||||||
|
vme->vm = vm;
|
||||||
|
|
||||||
|
e = create_event(VM, "polling", (void *)vme, 0, NULL, 0);
|
||||||
|
if (e) {
|
||||||
|
event_enqueue(e);
|
||||||
|
return VMEVT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(vme->vm_msg);
|
||||||
|
free(vme);
|
||||||
|
return VMEVT_DEFER;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback thread of a polling job.
|
* Callback thread of a polling job.
|
||||||
*/
|
*/
|
||||||
static void polling_vm(union sigval v __attribute__((unused)))
|
static void polling_vm(union sigval v __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
refresh_vm_history(get_sender_by_name("crashlog"), create_vm_event);
|
||||||
struct event_t *e = create_event(VM, "polling", NULL, 0, NULL, 0);
|
|
||||||
|
|
||||||
if (e)
|
|
||||||
event_enqueue(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
#include "event_handler.h"
|
#include "event_handler.h"
|
||||||
#include "startupreason.h"
|
#include "startupreason.h"
|
||||||
|
#include "android_events.h"
|
||||||
|
|
||||||
/* Watchdog timeout in second*/
|
/* Watchdog timeout in second*/
|
||||||
#define WDT_TIMEOUT 300
|
#define WDT_TIMEOUT 300
|
||||||
@ -135,6 +136,7 @@ static void *event_handle(void *unused __attribute__((unused)))
|
|||||||
int id;
|
int id;
|
||||||
struct sender_t *sender;
|
struct sender_t *sender;
|
||||||
struct event_t *e;
|
struct event_t *e;
|
||||||
|
struct vm_event_t *vme;
|
||||||
|
|
||||||
while ((e = event_dequeue())) {
|
while ((e = event_dequeue())) {
|
||||||
/* here we only handle internal event */
|
/* here we only handle internal event */
|
||||||
@ -173,6 +175,13 @@ static void *event_handle(void *unused __attribute__((unused)))
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->event_type == VM) {
|
||||||
|
vme = (struct vm_event_t *)e->private;
|
||||||
|
if (vme->vm_msg)
|
||||||
|
free(vme->vm_msg);
|
||||||
|
if (vme)
|
||||||
|
free(vme);
|
||||||
|
}
|
||||||
if ((e->dir))
|
if ((e->dir))
|
||||||
free(e->dir);
|
free(e->dir);
|
||||||
free(e);
|
free(e);
|
||||||
|
@ -11,7 +11,12 @@ extern char *loop_dev;
|
|||||||
|
|
||||||
#define VMEVT_HANDLED 0
|
#define VMEVT_HANDLED 0
|
||||||
#define VMEVT_DEFER -1
|
#define VMEVT_DEFER -1
|
||||||
#define VMEVT_MISSLOG -2
|
|
||||||
|
struct vm_event_t {
|
||||||
|
char *vm_msg;
|
||||||
|
size_t vm_msg_len;
|
||||||
|
const struct vm_t *vm;
|
||||||
|
};
|
||||||
|
|
||||||
#define ANDROID_LOGS_DIR "/logs/"
|
#define ANDROID_LOGS_DIR "/logs/"
|
||||||
#define IGN_SPACES "%*[[[:space:]]*]"
|
#define IGN_SPACES "%*[[[:space:]]*]"
|
||||||
|
@ -48,7 +48,7 @@ struct vm_t {
|
|||||||
ext2_filsys datafs;
|
ext2_filsys datafs;
|
||||||
unsigned long history_size[SENDER_MAX];
|
unsigned long history_size[SENDER_MAX];
|
||||||
char *history_data;
|
char *history_data;
|
||||||
char last_synced_line_key[SENDER_MAX][SHORT_KEY_LENGTH + 1];
|
char last_evt_detected[SENDER_MAX][SHORT_KEY_LENGTH + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct log_t {
|
struct log_t {
|
||||||
|
@ -586,8 +586,7 @@ static void telemd_send_reboot(void)
|
|||||||
free(class);
|
free(class);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int telemd_new_vmevent(const char *line_to_sync,
|
static void telemd_send_vmevent(struct event_t *e)
|
||||||
size_t len, const struct vm_t *vm)
|
|
||||||
{
|
{
|
||||||
char event[ANDROID_WORD_LEN];
|
char event[ANDROID_WORD_LEN];
|
||||||
char longtime[ANDROID_WORD_LEN];
|
char longtime[ANDROID_WORD_LEN];
|
||||||
@ -603,26 +602,20 @@ static int telemd_new_vmevent(const char *line_to_sync,
|
|||||||
int i;
|
int i;
|
||||||
uint32_t severity;
|
uint32_t severity;
|
||||||
int res;
|
int res;
|
||||||
int ret = VMEVT_HANDLED;
|
struct vm_event_t *vme;
|
||||||
|
|
||||||
/* VM events in history_event look like this:
|
|
||||||
*
|
|
||||||
* "CRASH xxxxxxxxxxxxxxxxxxxx 2017-11-11/03:12:59 JAVACRASH
|
|
||||||
* /data/logs/crashlog0_xxxxxxxxxxxxxxxxxxxx"
|
|
||||||
* "REBOOT xxxxxxxxxxxxxxxxxxxx 2011-11-11/11:20:51 POWER-ON
|
|
||||||
* 0000:00:00"
|
|
||||||
*/
|
|
||||||
const char * const vm_format =
|
const char * const vm_format =
|
||||||
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
|
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
|
||||||
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
|
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
|
||||||
|
|
||||||
res = str_split_ere(line_to_sync, len, vm_format, strlen(vm_format),
|
vme = (struct vm_event_t *)e->private;
|
||||||
event, sizeof(event), vmkey, sizeof(vmkey),
|
res = str_split_ere(vme->vm_msg, vme->vm_msg_len, vm_format,
|
||||||
longtime, sizeof(longtime),
|
strlen(vm_format), event, sizeof(event),
|
||||||
|
vmkey, sizeof(vmkey), longtime, sizeof(longtime),
|
||||||
type, sizeof(type), rest, sizeof(rest));
|
type, sizeof(type), rest, sizeof(rest));
|
||||||
if (res != 5) {
|
if (res != 5) {
|
||||||
LOGE("get an invalid line from (%s), skip\n", vm->name);
|
LOGE("get an invalid line from (%s), skip\n", vme->vm->name);
|
||||||
return VMEVT_HANDLED;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(event, "CRASH") == 0)
|
if (strcmp(event, "CRASH") == 0)
|
||||||
@ -633,30 +626,18 @@ static int telemd_new_vmevent(const char *line_to_sync,
|
|||||||
/* if line contains log, fill vmlogpath */
|
/* if line contains log, fill vmlogpath */
|
||||||
log = strstr(rest, ANDROID_LOGS_DIR);
|
log = strstr(rest, ANDROID_LOGS_DIR);
|
||||||
if (log) {
|
if (log) {
|
||||||
struct sender_t *crashlog = get_sender_by_name("crashlog");
|
|
||||||
const char *logf;
|
const char *logf;
|
||||||
size_t logflen;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (!crashlog)
|
|
||||||
return VMEVT_HANDLED;
|
|
||||||
|
|
||||||
|
if (!e->dir)
|
||||||
|
return;
|
||||||
logf = log + sizeof(ANDROID_LOGS_DIR) - 1;
|
logf = log + sizeof(ANDROID_LOGS_DIR) - 1;
|
||||||
logflen = &rest[0] + strnlen(rest, PATH_MAX) - logf;
|
if (asprintf(&vmlogpath, "%s/%s", e->dir, logf) == -1)
|
||||||
res = find_file(crashlog->outdir, crashlog->outdir_len, logf,
|
return;
|
||||||
logflen, 1, &vmlogpath, 1);
|
|
||||||
if (res == -1) {
|
|
||||||
LOGE("failed to find (%s) in (%s)\n",
|
|
||||||
logf, crashlog->outdir);
|
|
||||||
return VMEVT_DEFER;
|
|
||||||
} else if (res == 0)
|
|
||||||
return VMEVT_DEFER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = asprintf(&class, "%s/%s/%s", vm->name, event, type);
|
res = asprintf(&class, "%s/%s/%s", vme->vm->name, event, type);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
LOGE("compute string failed, out of memory\n");
|
LOGE("compute string failed, out of memory\n");
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
goto free_vmlogpath;
|
goto free_vmlogpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,15 +645,12 @@ static int telemd_new_vmevent(const char *line_to_sync,
|
|||||||
KEY_LONG);
|
KEY_LONG);
|
||||||
if (eventid == NULL) {
|
if (eventid == NULL) {
|
||||||
LOGE("generate eventid failed, error (%s)\n", strerror(errno));
|
LOGE("generate eventid failed, error (%s)\n", strerror(errno));
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
goto free_class;
|
goto free_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vmlogpath) {
|
if (!vmlogpath) {
|
||||||
res = telemd_send_data("no logs", eventid, severity, class);
|
telemd_send_data("vm event doesn't contain logs", eventid,
|
||||||
if (res == -1)
|
severity, class);
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
|
|
||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,33 +660,15 @@ static int telemd_new_vmevent(const char *line_to_sync,
|
|||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (!strstr(files[i], "/.") &&
|
if (!strstr(files[i], "/.") &&
|
||||||
!strstr(files[i], "/..")) {
|
!strstr(files[i], "/..")) {
|
||||||
res = telemd_send_data(files[i], eventid,
|
telemd_send_data(files[i], eventid, severity,
|
||||||
severity, class);
|
|
||||||
if (res == -1)
|
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (count == 2) {
|
|
||||||
char *content;
|
|
||||||
|
|
||||||
res = asprintf(&content, "no logs under (%s)", vmlogpath);
|
|
||||||
if (res > 0) {
|
|
||||||
res = telemd_send_data(content, eventid, severity,
|
|
||||||
class);
|
class);
|
||||||
if (res == -1)
|
}
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
free(content);
|
|
||||||
} else {
|
|
||||||
LOGE("compute string failed, out of memory\n");
|
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
}
|
}
|
||||||
} else if (count < 0) {
|
} else if (count < 0) {
|
||||||
LOGE("lsdir (%s) failed, error (%s)\n", vmlogpath,
|
LOGE("lsdir (%s) failed, error (%s)\n", vmlogpath,
|
||||||
strerror(-count));
|
strerror(-count));
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
} else {
|
} else {
|
||||||
LOGE("get (%d) files in (%s) ???\n", count, vmlogpath);
|
LOGE("get (%d) files in (%s) ???\n", count, vmlogpath);
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
@ -722,7 +682,7 @@ free_vmlogpath:
|
|||||||
if (vmlogpath)
|
if (vmlogpath)
|
||||||
free(vmlogpath);
|
free(vmlogpath);
|
||||||
|
|
||||||
return ret;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void telemd_send(struct event_t *e)
|
static void telemd_send(struct event_t *e)
|
||||||
@ -751,8 +711,7 @@ static void telemd_send(struct event_t *e)
|
|||||||
telemd_send_reboot();
|
telemd_send_reboot();
|
||||||
break;
|
break;
|
||||||
case VM:
|
case VM:
|
||||||
refresh_vm_history(get_sender_by_name("telemd"),
|
telemd_send_vmevent(e);
|
||||||
telemd_new_vmevent);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGE("unsupoorted event type %d\n", e->event_type);
|
LOGE("unsupoorted event type %d\n", e->event_type);
|
||||||
@ -946,8 +905,7 @@ static void crashlog_send_reboot(void)
|
|||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crashlog_new_vmevent(const char *line_to_sync,
|
static void crashlog_send_vmevent(struct event_t *e)
|
||||||
size_t len, const struct vm_t *vm)
|
|
||||||
{
|
{
|
||||||
char event[ANDROID_WORD_LEN];
|
char event[ANDROID_WORD_LEN];
|
||||||
char longtime[ANDROID_WORD_LEN];
|
char longtime[ANDROID_WORD_LEN];
|
||||||
@ -957,29 +915,28 @@ static int crashlog_new_vmevent(const char *line_to_sync,
|
|||||||
char *vmlogpath = NULL;
|
char *vmlogpath = NULL;
|
||||||
char *key;
|
char *key;
|
||||||
char *log;
|
char *log;
|
||||||
int ret = VMEVT_HANDLED;
|
|
||||||
int res;
|
int res;
|
||||||
int cnt;
|
int cnt;
|
||||||
char *dir;
|
ext2_filsys datafs;
|
||||||
|
struct sender_t *crashlog = get_sender_by_name("crashlog");
|
||||||
|
struct vm_event_t *vme;
|
||||||
|
enum vmrecord_mark_t mark = SUCCESS;
|
||||||
|
|
||||||
/* VM events in history_event like this:
|
|
||||||
*
|
|
||||||
* "CRASH xxxxxxxxxxxxxxxxxxxx 2017-11-11/03:12:59 JAVACRASH
|
|
||||||
* /data/logs/crashlog0_xxxxxxxxxxxxxxxxxxxx"
|
|
||||||
* "REBOOT xxxxxxxxxxxxxxxxxxxx 2011-11-11/11:20:51 POWER-ON
|
|
||||||
* 0000:00:00"
|
|
||||||
*/
|
|
||||||
const char * const vm_format =
|
const char * const vm_format =
|
||||||
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
|
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
|
||||||
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
|
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
|
||||||
|
|
||||||
res = str_split_ere(line_to_sync, len, vm_format, strlen(vm_format),
|
if (!crashlog)
|
||||||
event, sizeof(event), vmkey, sizeof(vmkey),
|
return;
|
||||||
longtime, sizeof(longtime),
|
|
||||||
|
vme = (struct vm_event_t *)e->private;
|
||||||
|
res = str_split_ere(vme->vm_msg, vme->vm_msg_len, vm_format,
|
||||||
|
strlen(vm_format), event, sizeof(event),
|
||||||
|
vmkey, sizeof(vmkey), longtime, sizeof(longtime),
|
||||||
type, sizeof(type), rest, sizeof(rest));
|
type, sizeof(type), rest, sizeof(rest));
|
||||||
if (res != 5) {
|
if (res != 5) {
|
||||||
LOGE("get an invalid line from (%s), skip\n", vm->name);
|
LOGE("get an invalid line from (%s), skip\n", vme->vm->name);
|
||||||
return ret;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = generate_event_id("SOS", 3, (const char *)vmkey,
|
key = generate_event_id("SOS", 3, (const char *)vmkey,
|
||||||
@ -987,64 +944,72 @@ static int crashlog_new_vmevent(const char *line_to_sync,
|
|||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
LOGE("generate event id failed, error (%s)\n",
|
LOGE("generate event id failed, error (%s)\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return VMEVT_DEFER;
|
mark = WAITING_SYNC;
|
||||||
|
goto mark_record;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crashlog_check_space() == -1) {
|
if (crashlog_check_space() == -1) {
|
||||||
hist_raise_event(vm->name, type, "SPACE_FULL", "", key);
|
hist_raise_event(vme->vm->name, type, "SPACE_FULL", "", key);
|
||||||
goto free_key;
|
goto free_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = generate_log_dir(MODE_VMEVENT, key);
|
e->dir = generate_log_dir(MODE_VMEVENT, key);
|
||||||
if (dir == NULL) {
|
if (e->dir == NULL) {
|
||||||
LOGE("generate crashlog dir failed\n");
|
LOGE("generate crashlog dir failed\n");
|
||||||
ret = VMEVT_DEFER;
|
mark = WAITING_SYNC;
|
||||||
goto free_key;
|
goto free_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_crashfile(dir, event, strnlen(event, ANDROID_WORD_LEN),
|
generate_crashfile(e->dir, event, strnlen(event, ANDROID_WORD_LEN),
|
||||||
key, SHORT_KEY_LENGTH,
|
key, SHORT_KEY_LENGTH,
|
||||||
type, strnlen(type, ANDROID_WORD_LEN),
|
type, strnlen(type, ANDROID_WORD_LEN),
|
||||||
vm->name, vm->name_len,
|
vme->vm->name, vme->vm->name_len,
|
||||||
vmkey, strnlen(vmkey, ANDROID_WORD_LEN), NULL, 0);
|
vmkey, strnlen(vmkey, ANDROID_WORD_LEN), NULL, 0);
|
||||||
|
|
||||||
/* if line contains log, we need dump each file in the logdir
|
log = strstr(rest, ANDROID_LOGS_DIR);
|
||||||
*/
|
if (!log)
|
||||||
log = strstr(rest, "/logs/");
|
goto raise_e;
|
||||||
if (log) {
|
|
||||||
|
/* if line contains log, we need dump each file in the logdir */
|
||||||
vmlogpath = log + 1;
|
vmlogpath = log + 1;
|
||||||
res = e2fs_dump_dir_by_dpath(vm->datafs, vmlogpath, dir, &cnt);
|
|
||||||
|
if (e2fs_open(loop_dev, &datafs) == -1) {
|
||||||
|
mark = WAITING_SYNC;
|
||||||
|
goto free_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = e2fs_dump_dir_by_dpath(datafs, vmlogpath, e->dir, &cnt);
|
||||||
|
e2fs_close(datafs);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
if (cnt) {
|
if (cnt) {
|
||||||
LOGE("dump (%s) abort at (%d)\n", vmlogpath,
|
LOGE("dump (%s) abort at (%d)\n", vmlogpath, cnt);
|
||||||
cnt);
|
mark = WAITING_SYNC;
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
} else {
|
} else {
|
||||||
LOGW("(%s) is missing\n", vmlogpath);
|
LOGW("(%s) doesn't exsit\n", vmlogpath);
|
||||||
ret = VMEVT_MISSLOG; /* missing logdir */
|
mark = MISS_LOG;
|
||||||
}
|
}
|
||||||
if (remove_r(dir) == -1)
|
|
||||||
LOGE("failed to remove %s (%d)\n", dir, -errno);
|
|
||||||
goto free_dir;
|
|
||||||
}
|
}
|
||||||
if (cnt == 1) {
|
if (cnt == 1) {
|
||||||
LOGW("(%s) is empty, will sync it in the next loop\n",
|
LOGW("%s is empty, will sync it in the next loop\n", vmlogpath);
|
||||||
vmlogpath);
|
mark = WAITING_SYNC;
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
if (remove_r(dir) == -1)
|
|
||||||
LOGE("failed to remove %s (%d)\n", dir, -errno);
|
|
||||||
goto free_dir;
|
|
||||||
}
|
}
|
||||||
|
if (res == -1 || cnt == -1) {
|
||||||
|
if (remove_r(e->dir) == -1)
|
||||||
|
LOGE("failed to remove %s, %s\n", e->dir,
|
||||||
|
strerror(errno));
|
||||||
|
free(e->dir);
|
||||||
|
e->dir = NULL;
|
||||||
|
goto free_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
hist_raise_event(vm->name, type, dir, "", key);
|
raise_e:
|
||||||
|
hist_raise_event(vme->vm->name, type, e->dir, "", key);
|
||||||
free_dir:
|
|
||||||
free(dir);
|
|
||||||
free_key:
|
free_key:
|
||||||
free(key);
|
free(key);
|
||||||
|
mark_record:
|
||||||
return ret;
|
vmrecord_open_mark(&crashlog->vmrecord, vmkey,
|
||||||
|
strnlen(vmkey, sizeof(vmkey)), mark);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void crashlog_send(struct event_t *e)
|
static void crashlog_send(struct event_t *e)
|
||||||
@ -1073,8 +1038,7 @@ static void crashlog_send(struct event_t *e)
|
|||||||
crashlog_send_reboot();
|
crashlog_send_reboot();
|
||||||
break;
|
break;
|
||||||
case VM:
|
case VM:
|
||||||
refresh_vm_history(get_sender_by_name("crashlog"),
|
crashlog_send_vmevent(e);
|
||||||
crashlog_new_vmevent);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGE("unsupoorted event type %d\n", e->event_type);
|
LOGE("unsupoorted event type %d\n", e->event_type);
|
||||||
@ -1083,7 +1047,6 @@ static void crashlog_send(struct event_t *e)
|
|||||||
|
|
||||||
int init_sender(void)
|
int init_sender(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
int id;
|
int id;
|
||||||
int fd;
|
int fd;
|
||||||
struct sender_t *sender;
|
struct sender_t *sender;
|
||||||
@ -1093,25 +1056,16 @@ int init_sender(void)
|
|||||||
if (!sender)
|
if (!sender)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = asprintf(&sender->vmrecord.path, "%s/VM_eventsID.log",
|
|
||||||
sender->outdir);
|
|
||||||
if (ret < 0) {
|
|
||||||
LOGE("compute string failed, out of memory\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
pthread_mutex_init(&sender->vmrecord.mtx, NULL);
|
|
||||||
|
|
||||||
if (!directory_exists(sender->outdir))
|
if (!directory_exists(sender->outdir))
|
||||||
if (mkdir_p(sender->outdir) < 0) {
|
if (mkdir_p(sender->outdir) < 0) {
|
||||||
LOGE("mkdir (%s) failed, error (%s)\n",
|
LOGE("mkdir (%s) failed, error (%s)\n",
|
||||||
sender->outdir, strerror(errno));
|
sender->outdir, strerror(errno));
|
||||||
return -errno;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = init_properties(sender);
|
if (init_properties(sender)) {
|
||||||
if (ret) {
|
|
||||||
LOGE("init sender failed\n");
|
LOGE("init sender failed\n");
|
||||||
exit(-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* touch uptime file, to add inotify */
|
/* touch uptime file, to add inotify */
|
||||||
@ -1121,16 +1075,23 @@ int init_sender(void)
|
|||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
LOGE("failed to open (%s), error (%s)\n",
|
LOGE("failed to open (%s), error (%s)\n",
|
||||||
uptime->path, strerror(errno));
|
uptime->path, strerror(errno));
|
||||||
return -errno;
|
return -1;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(sender->name, "crashlog")) {
|
if (!strcmp(sender->name, "crashlog")) {
|
||||||
sender->send = crashlog_send;
|
sender->send = crashlog_send;
|
||||||
ret = prepare_history();
|
if (prepare_history())
|
||||||
if (ret)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
if (asprintf(&sender->vmrecord.path,
|
||||||
|
"%s/VM_eventsID.log",
|
||||||
|
sender->outdir) == -1) {
|
||||||
|
LOGE("failed to asprintf\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pthread_mutex_init(&sender->vmrecord.mtx, NULL);
|
||||||
|
|
||||||
#ifdef HAVE_TELEMETRICS_CLIENT
|
#ifdef HAVE_TELEMETRICS_CLIENT
|
||||||
} else if (!strcmp(sender->name, "telemd")) {
|
} else if (!strcmp(sender->name, "telemd")) {
|
||||||
sender->send = telemd_send;
|
sender->send = telemd_send;
|
||||||
|
Loading…
Reference in New Issue
Block a user