luajit: prealloc lua states to increases chances of alloc success. Luajit requires them to be in memory <2GB.

pull/81/head
Victor Julien 13 years ago
parent f962e3de29
commit 98484ffdcc

@ -23,6 +23,8 @@
*/
#include "suricata-common.h"
#include "conf.h"
#include "threads.h"
#include "debug.h"
#include "decode.h"
@ -76,6 +78,8 @@ void DetectLuajitRegister(void) {
#else /* HAVE_LUAJIT */
#include "util-pool.h"
static int DetectLuajitMatch (ThreadVars *, DetectEngineThreadCtx *,
Packet *, Signature *, SigMatch *);
static int DetectLuajitSetup (DetectEngineCtx *, Signature *, char *);
@ -96,6 +100,21 @@ void DetectLuajitRegister(void) {
return;
}
/** \brief lua_State pool
*
* Luajit requires states to be alloc'd in memory <2GB. For this reason we
* prealloc the states early during engine startup so we have a better chance
* of getting the states. We protect the pool with a lock as the detect
* threads access it during their init and cleanup.
*
* Pool size is automagically determined based on number of keyword occurences,
* cpus/cores and rule reloads being enabled or not.
*
* Alternatively, the "detect-engine.luajit-states" var can be set.
*/
static Pool *luajit_states = NULL;
static pthread_mutex_t luajit_states_lock = PTHREAD_MUTEX_INITIALIZER;
#define DATATYPE_PACKET (1<<0)
#define DATATYPE_PAYLOAD (1<<1)
#define DATATYPE_STREAM (1<<2)
@ -114,6 +133,69 @@ void DetectLuajitRegister(void) {
#define DATATYPE_HTTP_RESPONSE_COOKIE (1<<11)
#define DATATYPE_HTTP_RESPONSE_BODY (1<<12)
static void *LuaStatePoolAlloc(void) {
return luaL_newstate();
}
static void LuaStatePoolClean(void *d) {
lua_State *s = (lua_State *)d;
if (s != NULL)
lua_close(s);
}
/** \brief Populate lua states pool
*
* \param num keyword instances
* \param reloads bool indicating we have rule reloads enabled
*/
int DetectLuajitSetupStatesPool(int num, int reloads) {
int retval = 0;
pthread_mutex_lock(&luajit_states_lock);
if (luajit_states == NULL) {
int cnt = 0;
char *conf_val = NULL;
if ((ConfGet("detect-engine.luajit-states", &conf_val)) == 1) {
cnt = (int)atoi(conf_val);
} else {
int cpus = UtilCpuGetNumProcessorsOnline();
if (cpus == 0) {
cpus = 10;
}
cnt = num * cpus;
/* alloc a bunch extra so reload can add new rules/instances */
if (reloads)
cnt *= 5;
}
luajit_states = PoolInit(0, cnt, 0, LuaStatePoolAlloc, NULL, NULL, LuaStatePoolClean);
if (luajit_states == NULL) {
SCLogError(SC_ERR_LUAJIT_ERROR, "luastate pool init failed, luajit keywords won't work");
retval = -1;
}
}
pthread_mutex_unlock(&luajit_states_lock);
return retval;
}
static lua_State *DetectLuajitGetState(void) {
lua_State *s = NULL;
pthread_mutex_lock(&luajit_states_lock);
if (luajit_states != NULL)
s = (lua_State *)PoolGet(luajit_states);
pthread_mutex_unlock(&luajit_states_lock);
return s;
}
static void DetectLuajitReturnState(lua_State *s) {
pthread_mutex_lock(&luajit_states_lock);
PoolReturn(luajit_states, (void *)s);
pthread_mutex_unlock(&luajit_states_lock);
}
/** \brief dump stack from lua state to screen */
void LuaDumpStack(lua_State *state) {
@ -382,10 +464,9 @@ static void *DetectLuajitThreadInit(void *data) {
t->alproto = luajit->alproto;
t->flags = luajit->flags;
t->luastate = luaL_newstate();
t->luastate = DetectLuajitGetState();
if (t->luastate == NULL) {
SCLogError(SC_ERR_LUAJIT_ERROR, "couldn't set up luastate");
SCLogError(SC_ERR_LUAJIT_ERROR, "luastate pool depleted");
goto error;
}
@ -406,8 +487,8 @@ static void *DetectLuajitThreadInit(void *data) {
return (void *)t;
error:
if (t->luastate)
lua_close(t->luastate);
if (t->luastate != NULL)
DetectLuajitReturnState(t->luastate);
SCFree(t);
return NULL;
}
@ -415,7 +496,8 @@ error:
static void DetectLuajitThreadFree(void *ctx) {
if (ctx != NULL) {
DetectLuajitThreadData *t = (DetectLuajitThreadData *)ctx;
lua_close(t->luastate);
if (t->luastate != NULL)
DetectLuajitReturnState(t->luastate);
SCFree(t);
}
}
@ -660,6 +742,8 @@ static int DetectLuajitSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
else
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
}
de_ctx->detect_luajit_instances++;
return 0;
error:

@ -50,4 +50,6 @@ typedef struct DetectLuajitData {
void DetectLuajitRegister (void);
int DetectLuajitMatchBuffer(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *sm, uint8_t *buffer, uint32_t buffer_len, uint32_t offset);
int DetectLuajitSetupStatesPool(int num, int reloads);
#endif /* __DETECT_FILELUAJIT_H__ */

@ -189,6 +189,7 @@
#include "runmodes.h"
extern uint8_t engine_mode;
extern int rule_reload;
extern int engine_analysis;
static int fp_engine_analysis_set = 0;
@ -2652,6 +2653,12 @@ int SigAddressPrepareStage1(DetectEngineCtx *de_ctx) {
"adding signatures to signature source addresses...");
}
/* run this before the mpm states are initialized */
if (DetectLuajitSetupStatesPool(de_ctx->detect_luajit_instances, rule_reload) != 0) {
if (de_ctx->failure_fatal)
return -1;
}
de_ctx->sig_array_len = DetectEngineGetMaxSigId(de_ctx);
de_ctx->sig_array_size = (de_ctx->sig_array_len * sizeof(Signature *));
de_ctx->sig_array = (Signature **)SCMalloc(de_ctx->sig_array_size);

@ -690,6 +690,8 @@ typedef struct DetectEngineCtx_ {
DetectEngineThreadKeywordCtxItem *keyword_list;
int keyword_id;
int detect_luajit_instances;
#ifdef PROFILING
struct SCProfileDetectCtx_ *profile_ctx;
#endif

@ -204,6 +204,8 @@ SC_ATOMIC_DECLARE(unsigned int, engine_stage);
/* Max packets processed simultaniously. */
#define DEFAULT_MAX_PENDING_PACKETS 1024
int rule_reload = 0;
/** suricata engine control flags */
uint8_t suricata_ctl_flags = 0;
@ -685,7 +687,6 @@ int main(int argc, char **argv)
uint32_t groupid = 0;
#endif /* OS_WIN32 */
int build_info = 0;
int rule_reload = 0;
int delayed_detect = 0;
char *log_dir;

Loading…
Cancel
Save