static void *thread_main_loop(void *_state) { struct thread_state *state = (struct thread_state *)_state; struct packet *pkt = NULL; sigset_t set; #ifdef HAKA_MEMCHECK int64 pkt_count=0; const int mem_rate=10; #endif thread_setid(state->thread_id); if (!state->pool->single) { /* Block all signal to let the main thread handle them */ sigfillset(&set); sigdelset(&set, SIGSEGV); sigdelset(&set, SIGILL); sigdelset(&set, SIGFPE); if (!thread_sigmask(SIG_BLOCK, &set, NULL)) { LOG_FATAL(core, "%s", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } if (!timer_init_thread()) { LOG_FATAL(core, "%s", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } /* To make sure we can still cancel even if some thread are locked in * infinite loops */ if (!thread_setcanceltype(THREAD_CANCEL_ASYNCHRONOUS)) { LOG_FATAL(core, "%s", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } if (!init_thread_lua_state(state)) { barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } } state->engine = engine_thread_init(state->lua->L, state->thread_id); engine_thread_update_status(state->engine, THREAD_RUNNING); packet_init(state->capture); if (!state->pool->single) { if (!barrier_wait(&state->pool->thread_start_sync)) { LOG_FATAL(core, "%s", clear_error()); state->state = STATE_ERROR; engine_thread_update_status(state->engine, THREAD_DEFUNC); return NULL; } } if (!state->pool->single) { if (!barrier_wait(&state->pool->thread_sync)) { LOG_FATAL(core, "%s", clear_error()); state->state = STATE_ERROR; engine_thread_update_status(state->engine, THREAD_DEFUNC); return NULL; } } lua_state_trigger_haka_event(state->lua, "started"); engine_thread_update_status(state->engine, THREAD_WAITING); while (packet_receive(state->engine, &pkt) == 0) { engine_thread_update_status(state->engine, THREAD_RUNNING); /* The packet can be NULL in case of failure in packet receive */ if (pkt) { filter_wrapper(state, pkt); pkt = NULL; } lua_state_runinterrupt(state->lua); engine_thread_check_remote_launch(state->engine); if (state->pool->attach_debugger > state->attach_debugger) { luadebug_debugger_start(state->lua->L, true); state->attach_debugger = state->pool->attach_debugger; } engine_thread_update_status(state->engine, THREAD_WAITING); #ifdef HAKA_MEMCHECK if (((pkt_count++) % mem_rate) == 0) { size_t vmsize, rss; if (!get_memory_size(&vmsize, &rss)) { LOG_ERROR(core, "cannot get memory report: %s", clear_error()); } else { const size_t luasize = lua_gc(state->lua->L, LUA_GCCOUNT, 0); LOG_DEBUG(core, "memory report: thread=%d vmsize=%zd rsssize=%zd luasize=%zd", engine_thread_id(state->engine), vmsize, rss, luasize); } } #endif if (state->pool->stop) { break; } } state->state = STATE_FINISHED; engine_thread_update_status(state->engine, THREAD_STOPPED); return NULL; }
struct thread_pool *thread_pool_create(int count, struct packet_module *packet_module, bool attach_debugger, bool dissector_graph) { int i; struct thread_pool *pool; assert(count > 0); engine_prepare(count); pool = malloc(sizeof(struct thread_pool)); if (!pool) { error("memory error"); return NULL; } memset(pool, 0, sizeof(struct thread_pool)); pool->threads = malloc(sizeof(struct thread_state*)*count); if (!pool) { error("memory error"); thread_pool_cleanup(pool); return NULL; } memset(pool->threads, 0, sizeof(struct thread_state*)*count); pool->count = count; pool->single = count == 1; pool->stop = false; if (!barrier_init(&pool->thread_sync, count+1)) { thread_pool_cleanup(pool); return NULL; } if (!barrier_init(&pool->thread_start_sync, 2)) { thread_pool_cleanup(pool); return NULL; } if (attach_debugger) { thread_pool_attachdebugger(pool); } for (i=0; i<count; ++i) { pool->threads[i] = init_thread_state(packet_module, i, dissector_graph); if (!pool->threads[i]) { error("thread initialization error"); thread_pool_cleanup(pool); return NULL; } pool->threads[i]->pool = pool; if (pool->single) { if (!init_thread_lua_state(pool->threads[i])) { error("thread initialization error"); thread_pool_cleanup(pool); return NULL; } } else { if (!thread_create(&pool->threads[i]->thread, thread_main_loop, pool->threads[i])) { thread_pool_cleanup(pool); return NULL; } pool->threads[i]->state = STATE_RUNNING; if (!barrier_wait(&pool->thread_start_sync)) { thread_pool_cleanup(pool); return NULL; } if (pool->threads[i]->state == STATE_ERROR) { error("thread initialization error"); thread_pool_cleanup(pool); return NULL; } } } return pool; }
static void *thread_main_loop(void *_state) { struct thread_state *state = (struct thread_state *)_state; struct packet *pkt = NULL; sigset_t set; thread_setid(state->thread_id); if (!state->pool->single) { /* Block all signal to let the main thread handle them */ sigfillset(&set); sigdelset(&set, SIGSEGV); sigdelset(&set, SIGILL); sigdelset(&set, SIGFPE); if (!thread_sigmask(SIG_BLOCK, &set, NULL)) { message(HAKA_LOG_FATAL, "core", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } if (!timer_init_thread()) { message(HAKA_LOG_FATAL, "core", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } /* To make sure we can still cancel even if some thread are locked in * infinite loops */ if (!thread_setcanceltype(THREAD_CANCEL_ASYNCHRONOUS)) { message(HAKA_LOG_FATAL, "core", clear_error()); barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } if (!init_thread_lua_state(state)) { barrier_wait(&state->pool->thread_start_sync); state->state = STATE_ERROR; return NULL; } } state->engine = engine_thread_init(state->lua->L, state->thread_id); engine_thread_update_status(state->engine, THREAD_RUNNING); packet_init(state->capture); if (!state->pool->single) { if (!barrier_wait(&state->pool->thread_start_sync)) { message(HAKA_LOG_FATAL, "core", clear_error()); state->state = STATE_ERROR; engine_thread_update_status(state->engine, THREAD_DEFUNC); return NULL; } } if (!state->pool->single) { if (!barrier_wait(&state->pool->thread_sync)) { message(HAKA_LOG_FATAL, "core", clear_error()); state->state = STATE_ERROR; engine_thread_update_status(state->engine, THREAD_DEFUNC); return NULL; } } lua_state_trigger_haka_event(state->lua, "started"); engine_thread_update_status(state->engine, THREAD_WAITING); while (packet_receive(&pkt) == 0) { engine_thread_update_status(state->engine, THREAD_RUNNING); /* The packet can be NULL in case of failure in packet receive */ if (pkt) { filter_wrapper(state, pkt); pkt = NULL; } lua_state_runinterrupt(state->lua); engine_thread_check_remote_launch(state->engine); if (state->pool->attach_debugger > state->attach_debugger) { luadebug_debugger_start(state->lua->L, true); state->attach_debugger = state->pool->attach_debugger; } engine_thread_update_status(state->engine, THREAD_WAITING); if (state->pool->stop) { break; } } state->state = STATE_FINISHED; engine_thread_update_status(state->engine, THREAD_STOPPED); return NULL; }