diff options
| author | Qiuwen Lu <[email protected]> | 2016-12-12 19:39:45 +0800 |
|---|---|---|
| committer | Qiuwen Lu <[email protected]> | 2016-12-12 19:39:45 +0800 |
| commit | e5a7bf9cfa911f3b04773e55c81a5354d2d0c6d2 (patch) | |
| tree | 38c2bd24857ae755344c7cb4b01873a65003b7df | |
| parent | 83b7454286dd555c5e98bc4667c3fd51653ba3d4 (diff) | |
增加崩溃检测与回调函数框架
| -rw-r--r-- | app/src/marsio.c | 12 | ||||
| -rw-r--r-- | include/internal/mr_common.h | 8 | ||||
| -rw-r--r-- | runtime/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | runtime/include/mr_runtime.h | 7 | ||||
| -rw-r--r-- | runtime/include/runtime.h | 17 | ||||
| -rw-r--r-- | runtime/src/app.c | 25 | ||||
| -rw-r--r-- | runtime/src/event.c | 444 | ||||
| -rw-r--r-- | runtime/src/export.c | 15 | ||||
| -rw-r--r-- | runtime/src/runtime.c | 8 |
9 files changed, 534 insertions, 5 deletions
diff --git a/app/src/marsio.c b/app/src/marsio.c index 3c3a875..2b25cb4 100644 --- a/app/src/marsio.c +++ b/app/src/marsio.c @@ -154,12 +154,12 @@ static int mrapp_init(const char * appsym, struct mrapp_config * config) { // У����� int ret = mrapp_config_check(appsym, config); - if(ret < 0) + if (ret < 0) { MR_LOG(ERR, MRLIB, "Marsio config check failed. \n"); return ret; } - + // Ӧ��ע�� ret = mr_app_register(appsym, config->coremask, config->autoexit); if (ret < 0) @@ -168,6 +168,14 @@ static int mrapp_init(const char * appsym, struct mrapp_config * config) return -1; } + // ������� + ret = mr_app_crash_raiser_register(appsym); + if(ret < 0) + { + MR_LOG(ERR, MRLIB, "Cannot register application %s crash monitor. \n", appsym); + return -2; + } + MR_LOG(INFO, MRLIB, "Application %s register success. \n", appsym); // ������̵�Privָ�벻Ϊ�գ�˵����ǰ���й����ָ������� diff --git a/include/internal/mr_common.h b/include/internal/mr_common.h index 3911a26..1843002 100644 --- a/include/internal/mr_common.h +++ b/include/internal/mr_common.h @@ -116,6 +116,14 @@ static inline const char * __str_errno() return rte_strerror(rte_errno); } +#ifdef __GNUC__ +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type,member));}) +#else +#define container_of(ptr, type,member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) +#endif #ifdef __cplusplus } diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e2ad0c6..b681298 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories(${DPDK_INCLUDE_DIR}) add_definitions(${DPDK_C_PREDEFINED})
include_directories(include)
-add_library(mruntime src/app.c src/ctx.c src/runtime.c src/hwinfo.c src/id.c src/export.c)
+add_library(mruntime src/app.c src/ctx.c src/runtime.c src/hwinfo.c src/id.c
+ src/event.c src/export.c)
target_link_libraries(mruntime PRIVATE rt pthread dl)
target_include_directories(mruntime INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/")
\ No newline at end of file diff --git a/runtime/include/mr_runtime.h b/runtime/include/mr_runtime.h index 94e27f6..7704e1a 100644 --- a/runtime/include/mr_runtime.h +++ b/runtime/include/mr_runtime.h @@ -61,4 +61,9 @@ unsigned int mr_appinfo_get_nr_max_thread(struct appinfo * appinfo); void * mr_app_priv_get(); void mr_app_priv_set(void * ptr); void * mr_thread_priv_get(); -void mr_thread_priv_set(void * ptr);
\ No newline at end of file +void mr_thread_priv_set(void * ptr); + +typedef void(*app_event_cb_t)(int app_event, const char * appsym, + struct appinfo * appinfo, void * arg); +int mr_app_crash_cb_register(app_event_cb_t cb, void * arg); +int mr_app_crash_raiser_register(const char * appsym);
\ No newline at end of file diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index 744f9d0..5fcc08e 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -5,6 +5,8 @@ struct app_manager; struct hwinfo_manager; struct id_manager; +struct app_ev_manager; +struct appinfo; #ifndef MR_RUNTIME_MAX_NR_EXIT_HANDLER #define MR_RUNTIME_MAX_NR_EXIT_HANDLER 64 @@ -16,6 +18,7 @@ struct mr_runtime_ctx struct app_manager * app_ctx; struct hwinfo_manager * hwinfo_ctx; struct id_manager * id_ctx; + struct app_ev_manager * ev_ctx; }; extern struct app_manager * app_manager_create(); @@ -38,6 +41,9 @@ extern int app_manager_appinfo_unregister(struct app_manager * object); extern int app_manager_thread_register(struct app_manager * object); extern int app_manager_thread_unregister(struct app_manager * object); extern int app_manager_appinfo_iterate(struct app_manager * object, struct appinfo ** appinfo); +extern struct appinfo * app_mamager_appinfo_lookup(struct app_manager * object, const char * appsym); +extern void app_mamager_crash_event_handler(int app_event, const char * appsym, + struct appinfo * appinfo, void * arg); // ��������������� extern struct id_manager * id_manager_create(); @@ -51,4 +57,13 @@ extern int id_manager_release_gsid(struct id_manager * object, thread_id_t start extern int mr_global_ctx_init(); extern int mr_global_ctx_slave_init(); extern int mr_global_cfg_init(); -extern int mr_global_cfg_slave_init();
\ No newline at end of file +extern int mr_global_cfg_slave_init(); + +// ������� +struct app_ev_manager * app_ev_manager_create(struct mr_runtime_ctx * rt_ctx); +void app_ev_manager_destory(struct app_ev_manager * object); + +typedef void(*app_event_cb_t)(int app_event, const char * appsym, struct appinfo * appinfo, void * arg); +int app_crash_cb_register(struct app_ev_manager * object, app_event_cb_t cb, void * arg); +int app_crash_raiser_register(struct app_ev_manager * object, const char * appsym); +void * app_thread_crash_monitor(void * arg);
\ No newline at end of file diff --git a/runtime/src/app.c b/runtime/src/app.c index f7e2ac3..ea1980a 100644 --- a/runtime/src/app.c +++ b/runtime/src/app.c @@ -457,6 +457,21 @@ int app_manager_appinfo_unregister(struct app_manager * object) return ret; } +#if 0 +typedef void(*app_event_cb_t)(int app_event, const char * appsym, + struct appinfo * appinfo, void * arg); +#endif + +void app_mamager_crash_event_handler(int app_event, const char * appsym, + struct appinfo * appinfo, void * arg) +{ + struct app_manager * object = (struct app_manager *)arg; + + mr_spin_lock(&object->lock); + __appinfo_delete_unsafe(object, appinfo); + mr_spin_unlock(&object->lock); +} + int app_manager_thread_register(struct app_manager * object) { struct appinfo * pinfo = currect_app_info; @@ -521,6 +536,16 @@ int app_manager_list_all_appinfo(struct app_manager * object, return ret; } +struct appinfo * app_mamager_appinfo_lookup(struct app_manager * object, + const char * appsym) +{ + struct appinfo * result = NULL; + mr_spin_lock(&object->lock); + result = __appinfo_lookup_unsafe(object, appsym); + mr_spin_unlock(&object->lock); + return result; +} + int app_manager_tinfo_iterate(struct appinfo * appinfo, struct thread_info ** tinfo, int * iterate) { diff --git a/runtime/src/event.c b/runtime/src/event.c new file mode 100644 index 0000000..f27d376 --- /dev/null +++ b/runtime/src/event.c @@ -0,0 +1,444 @@ +/* \brief Ӧ�ó����쳣״̬������¼�֪ͨ + * + * ���Ӧ���쳣�˳�״̬����֪ͨ�����̸�ģ�����Ӧ��ʹ�õ���Դ + * TODO: �ع����δ��룬֧�ָ�����첽�ź�֪ͨ���� + * + * \author Qiuwen Lu<[email protected]> + * \date 2016-12-09 + */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <sys/epoll.h> +#include <assert.h> +#include <rte_malloc.h> +#include <rte_devargs.h> + +#include <mr_common.h> +#include <mr_runtime.h> +#include <runtime.h> + +TAILQ_HEAD(crash_ev_raiser_list, crash_ev_raiser); +TAILQ_HEAD(crash_ev_cb_list, crash_ev_cb); + +/* �����¼�Դ */ +struct crash_ev_raiser +{ + TAILQ_ENTRY(crash_ev_raiser) next; + struct appinfo * appinfo; + char appsym[MR_SYMBOL_MAX]; + int connect_fd; +}; + +/* �����¼��������� */ +struct crash_ev_cb +{ + TAILQ_ENTRY(crash_ev_cb) next; + app_event_cb_t cb; + void * arg; +}; + +/* �����¼�Դע��ָ�ͨ��TCP���䣩 */ +struct crash_raiser_reg_cmd +{ + /* ���� */ + char symlen; + /* ���� */ + char appsym[MR_SYMBOL_MAX]; +}; + +struct app_ev_manager +{ +#define __MAX_CRASH_CBS 64 + + /* Rt��� */ + struct mr_runtime_ctx * rt_ctx; + /* Ӧ�ñ����¼�Դ */ + struct crash_ev_raiser_list crash_ev_raiser_list; + /* Ӧ�ñ����¼������ص����� */ + struct crash_ev_cb_list crash_ev_cb_list; + /* Ӧ�ñ�������ַ */ + struct sockaddr_in crash_sockaddr; +}; + +struct app_ev_manager * app_ev_manager_create(struct mr_runtime_ctx * rt_ctx) +{ + struct app_ev_manager * object = rte_zmalloc(NULL, sizeof(struct app_ev_manager), 0); + MR_CHECK(object != NULL, "Cannot alloc memory for app event manager"); + + object->rt_ctx = rt_ctx; + TAILQ_INIT(&object->crash_ev_cb_list); + TAILQ_INIT(&object->crash_ev_raiser_list); + return object; +} + +void app_ev_manager_destory(struct app_ev_manager * object) +{ + rte_free(object); +} + +/* ע������������� */ +int app_crash_cb_register(struct app_ev_manager * object, app_event_cb_t cb, + void * arg) +{ + struct crash_ev_cb * ev_cb = rte_zmalloc(NULL, sizeof(struct crash_ev_cb), 0); + MR_CHECK(ev_cb != NULL, "Cannot alloc memory for crash_ev_cb"); + + ev_cb->cb = cb; + ev_cb->arg = arg; + TAILQ_INSERT_TAIL(&object->crash_ev_cb_list, ev_cb, next); + return 0; +} + +/* ע������¼�Դ */ +int app_crash_raiser_register(struct app_ev_manager * object, const char * appsym) +{ + int conn_fd = socket(AF_INET, SOCK_STREAM, 0); + if (unlikely(conn_fd < 0)) + { + MR_LOG(ERR, BASE, "Cannot create socket for crash raiser register : %s. \n", + strerror(errno)); + return -1; + } + + int ret = connect(conn_fd, (const struct sockaddr *)&object->crash_sockaddr, + sizeof(object->crash_sockaddr)); + + if (unlikely(ret < 0)) + { + MR_LOG(ERR, BASE, "Connect to crash monitor failed : %s", strerror(errno)); + return -2; + } + + struct crash_raiser_reg_cmd reg_cmd; + snprintf(reg_cmd.appsym, sizeof(reg_cmd.appsym), "%s", appsym); + reg_cmd.symlen = strlen(reg_cmd.appsym); + + do {
+ ret = send(conn_fd, ®_cmd, sizeof(reg_cmd), MSG_NOSIGNAL);
+ } while (ret == -1 && (errno == EINTR)); + + assert(ret == sizeof(reg_cmd)); + return 0; +} + +/* �¼���������ע��Ӧ�� */ +static int app_crash_handle_new_raiser(struct app_ev_manager * object, + const char * appsym, int conn_fd) +{ + struct mr_runtime_ctx * rt_ctx = object->rt_ctx; + struct app_manager * app_manager = rt_ctx->app_ctx; + + struct appinfo * appinfo = app_mamager_appinfo_lookup(app_manager, appsym); + if (appinfo == NULL) + { + MR_LOG(ERR, BASE, "Application %s does not existed, " + "cannot monitor its crash state. \n", appsym); + return -1; + } + + struct crash_ev_raiser * raiser; + +#ifndef _NDEBUG + TAILQ_FOREACH(raiser, &object->crash_ev_raiser_list, next) + { + assert(strcmp(raiser->appsym, appsym) != 0); + } +#endif + + raiser = rte_zmalloc(NULL, sizeof(struct crash_ev_raiser), 0); + MR_CHECK(raiser != NULL, "Cannot alloc memory for crash raiser. "); + + snprintf(raiser->appsym, sizeof(raiser->appsym), "%s", appsym); + raiser->appinfo = appinfo; + raiser->connect_fd = conn_fd; + TAILQ_INSERT_TAIL(&object->crash_ev_raiser_list, raiser, next); + + MR_LOG(INFO, BASE, "Crash raiser from application %s registed. \n", appsym); + return 0; +} + +/* �¼�������Ӧ�ñ��� */ +static int app_crash_handle_crash_raiser(struct app_ev_manager * object, + struct crash_ev_raiser * raiser) +{ + MR_LOG(INFO, BASE, "Crash raise from applicaion %s. \n", raiser->appsym); + + struct crash_ev_cb * cb; + TAILQ_FOREACH(cb, &object->crash_ev_cb_list, next) + { + cb->cb(0, raiser->appsym, raiser->appinfo, cb->arg); + } + + TAILQ_REMOVE(&object->crash_ev_raiser_list, raiser, next); + rte_free(raiser); + return 0; +} + +#define __LISTEN_PORT_START 1024 +#define __LISTEN_PORT_END 65535 +#define __LISTEN_BACKEND 16 + +static int __create_monitor_fd(struct sockaddr_in * sockaddr_in) +{ + int try_times_max = 36; + int success = 0; + + // �������ض˿ڣ�TCP���� + int listen_fd = socket(AF_INET, SOCK_STREAM, 0); + if(unlikely(listen_fd < 0)) + { + MR_LOG(ERR, BASE, "Create crash monitor listen fd failed : %s. \n", + strerror(errno)); + goto out; + } + + int reuse = 1; + if (unlikely(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, + (const void*)&reuse, sizeof(int)) < 0))
+ {
+ MR_LOG(ERR, BASE, "Set crash monitor listen fd reuse failed : %s\n", + strerror(errno)); + goto out;
+ } + + while (try_times_max >= 0) + { + unsigned int random_port; + + // ���ѡ��һ�������˿ڣ����ؼ��� + random_port = rand() % (__LISTEN_PORT_END - __LISTEN_PORT_START) + __LISTEN_PORT_START; + assert(random_port >= __LISTEN_PORT_START && random_port <= __LISTEN_PORT_END); + + memset(sockaddr_in, 0, sizeof(struct sockaddr_in)); + sockaddr_in->sin_family = AF_INET; + sockaddr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in->sin_port = htons(random_port); + + int ret = bind(listen_fd, (struct sockaddr *)sockaddr_in, + sizeof(struct sockaddr_in)); + + // �˿ڱ�ռ�ã�����ѡ��һ�����õĶ˿� + if (ret < 0 && errno == EADDRINUSE) + { + try_times_max--; + continue; + } + + // �������� + else if (ret < 0) + { + MR_LOG(ERR, BASE, "Bind crash monitor listen fd(PORT=%d) failed : %s.\n", + random_port, strerror(errno)); + goto out; + } + + ret = listen(listen_fd, 20); + if(ret < 0) + { + MR_LOG(ERR, BASE, "Listen crash monitor listen fd(PORT=%d) failed : %s.\n", + random_port, strerror(errno)); + goto out; + } + + success = 1; + break; + } + + if(success) + { + MR_LOG(INFO, BASE, "Crash monitor listen tcp fd(port=%d) create success.\n", + ntohs(sockaddr_in->sin_port)); + return listen_fd; + } + +out: + if (listen_fd > 0) close(listen_fd); + return -1; +} + +#define __EV_MAX_EVENTS 16 +#define __EV_MAX_BUFFER 2048 + + +// ���¹��ߺ�����MESATCP�н�ȡ +static int __tcp_setnonblock(int sockfd)
+{
+ int flags = fcntl(sockfd, F_GETFL, 0);
+ if (flags == -1) return -1;
+ int ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK, 0);
+ if (ret == -1) return -1;
+ return 0;
+} + +static int __update_epoll_event(int epoll_fd, int epoll_mode, int fd, int epoll_type)
+{
+ struct epoll_event event = { 0 };
+ event.data.fd = fd;
+ event.events = epoll_type; + + __tcp_setnonblock(fd);
+ if (-1 == epoll_ctl(epoll_fd, epoll_mode, fd, &event))
+ {
+ MR_LOG(ERR, BASE, "update epoll event failed : %s\n", + strerror(errno)); return -1;
+ }
+
+ return 0;
+} + +int __epoll_add_event(int epoll_fd, int sd, int epoll_type)
+{
+ return __update_epoll_event(epoll_fd, EPOLL_CTL_ADD, sd, epoll_type);
+}
+
+int __epoll_del_event(int epoll_fd, int sd, int epoll_type)
+{
+ return __update_epoll_event(epoll_fd, EPOLL_CTL_DEL, sd, epoll_type);
+}
+
+int __epoll_mod_event(int epoll_fd, int sd, int epoll_type)
+{
+ return __update_epoll_event(epoll_fd, EPOLL_CTL_MOD, sd, epoll_type);
+} + +/* �����½��ļ������� */ +void __handle_accept(struct app_ev_manager * object, int epoll_fd, int listen_fd) +{ + struct sockaddr_in remote_addr; + socklen_t sz_remote_addr = sizeof(remote_addr); + + int conn_fd = accept(listen_fd, (struct sockaddr *)&remote_addr, &sz_remote_addr); + if(conn_fd < 0) + { + MR_LOG(ERR, BASE, "Accept remote connnection failed : %s", strerror(errno)); + return; + } + + __epoll_add_event(epoll_fd, conn_fd, EPOLLIN); + return; +} + +// �������ӹر���Ϣ�����ӹرմ���Ӧ�ñ��� +void __handle_close(struct app_ev_manager * object, int epoll_fd, int fd) +{ + struct crash_ev_raiser * raiser_iter; + TAILQ_FOREACH(raiser_iter, &object->crash_ev_raiser_list, next) + { + if (raiser_iter->connect_fd != fd) continue; + app_crash_handle_crash_raiser(object, raiser_iter); + } + + __epoll_del_event(epoll_fd, fd, EPOLLIN); + close(fd); + return; +} + +/* �����������ӵ�������� */ +void __handle_read(struct app_ev_manager * object, int epoll_fd, int fd) +{ + // ���뻺��������������С����ָ��� + char __read_buffer[sizeof(struct crash_raiser_reg_cmd)]; + ssize_t __read_buffer_used = 0; + ssize_t ret = 0; + + while ((ret = read(fd, __read_buffer + __read_buffer_used, + sizeof(__read_buffer) - __read_buffer_used)) > 0) + { + __read_buffer_used += ret; + } + + // ���ݶ���������ָ�� + if(__read_buffer_used == sizeof(struct crash_raiser_reg_cmd)) + { + struct crash_raiser_reg_cmd * cmd = (struct crash_raiser_reg_cmd *)__read_buffer; + if (cmd->symlen != strnlen(cmd->appsym, sizeof(cmd->appsym))) return; + app_crash_handle_new_raiser(object, cmd->appsym, fd); + return; + } + + if(ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) + { + return; + } + + if (ret == 0) + { + __handle_close(object, epoll_fd, fd); + return; + } + + //TODO: ��������������� + assert(0); + return; +} + +/* ��������߳� */ +//TODO: ���Epoll��ͨ�Ż��ƣ������Libevent�� + +void * app_thread_crash_monitor(void * arg) +{ + struct app_ev_manager * object = (struct app_ev_manager *)arg; + pthread_detach(pthread_self()); + + int listen_fd = __create_monitor_fd(&object->crash_sockaddr); + if(listen_fd < 0) + { + MR_LOG(ERR, BASE, "Launch crash monitor thread failed : " + "Cannot create listen fd. \n"); goto errout; + } + + int epoll_fd = epoll_create(16); + if(epoll_fd < 0) + { + MR_LOG(ERR, BASE, "Launch crash monitor thread failed : " + "Cannot create epoll fd. \n"); goto errout; + } + + struct epoll_event evlist[__EV_MAX_EVENTS]; + struct epoll_event ev; + + ev.events = EPOLLIN; + ev.data.fd = listen_fd; + if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0) + { + MR_LOG(ERR, BASE, "Crash monitor thread failed : " + "Add listenfd to epoll list error : %s \n", strerror(errno)); + goto errout; + } + + while(1) + { + int ret = epoll_wait(epoll_fd, evlist, __EV_MAX_EVENTS, 0); + if (ret == -1 && errno == EINTR) continue; + else if(ret == -1) + { + MR_LOG(ERR, BASE, "Crash monitor thread failed : " + "waiting on epoll fd : %s", strerror(errno)); + goto errout; + } + + for(int i = 0; i < ret; i++) + { + int fd = evlist[i].data.fd; + if(evlist[i].events & EPOLLIN) + { + if (fd == listen_fd) __handle_accept(object, epoll_fd, fd); + else __handle_read(object, epoll_fd, fd); + continue; + } + + if(evlist[i].events & ( EPOLLHUP | EPOLLERR)) + { + __handle_close(object, epoll_fd, fd); + } + } + } + +errout: + MR_LOG(ERR, BASE, "Crash monitor thread is exiting. \n"); + return (void *)NULL; +}
\ No newline at end of file diff --git a/runtime/src/export.c b/runtime/src/export.c index 6a145c3..a4b755a 100644 --- a/runtime/src/export.c +++ b/runtime/src/export.c @@ -103,3 +103,18 @@ int mr_id_manager_release_gsid(thread_id_t start_gsid, struct mr_runtime_ctx * rt_ctx = (struct mr_runtime_ctx *)g_ctx->ctx_runtime; return id_manager_release_gsid(rt_ctx->id_ctx, start_gsid, nr_thread); } + +// ������������ +int mr_app_crash_cb_register(app_event_cb_t cb, void * arg) +{ + struct mr_global_ctx * g_ctx = mr_global_ctx_get(); + struct mr_runtime_ctx * rt_ctx = (struct mr_runtime_ctx *)g_ctx->ctx_runtime; + return app_crash_cb_register(rt_ctx->ev_ctx, cb, arg); +} + +int mr_app_crash_raiser_register(const char * appsym) +{ + struct mr_global_ctx * g_ctx = mr_global_ctx_get(); + struct mr_runtime_ctx * rt_ctx = (struct mr_runtime_ctx *)g_ctx->ctx_runtime; + return app_crash_raiser_register(rt_ctx->ev_ctx, appsym); +}
\ No newline at end of file diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 37bec21..88e912e 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -43,6 +43,14 @@ void mr_runtime_init() rt_ctx->id_ctx = id_manager_create(); MR_CHECK(rt_ctx->id_ctx != NULL, "RuntimeInit, ID Manager initialize failed. "); + + rt_ctx->ev_ctx = app_ev_manager_create(rt_ctx); + MR_CHECK(rt_ctx->ev_ctx != NULL, "RuntimeInit, App event initialize failed. "); + + pthread_t pid_crash_monitor; + pthread_create(&pid_crash_monitor, NULL, app_thread_crash_monitor, (void *)rt_ctx->ev_ctx); + + app_crash_cb_register(rt_ctx->ev_ctx, app_mamager_crash_event_handler, rt_ctx->app_ctx); g_ctx->ctx_runtime = rt_ctx; return; |
