Using malloc/free for the http fields hash.

This is required due to lack of a graceful shutdown: there is a small gap
between the runtime's memory pool release and router process's exit. Thus, a
worker thread may start processing a request between these two operations,
which may result in an http fields hash access and subsequent crash.

To simplify issue reproduction, it makes sense to add a 2 sec sleep before
exit() in nxt_runtime_exit().
This commit is contained in:
Max Romanov
2020-04-16 17:09:23 +03:00
parent ee62736a11
commit 6bda9b5eeb
9 changed files with 24 additions and 52 deletions

View File

@@ -130,14 +130,11 @@ nxt_controller_start(nxt_task_t *task, void *data)
nxt_mp_t *mp;
nxt_int_t ret;
nxt_str_t *json;
nxt_runtime_t *rt;
nxt_conf_value_t *conf;
nxt_conf_validation_t vldt;
nxt_controller_init_t *init;
rt = task->thread->runtime;
ret = nxt_http_fields_hash(&nxt_controller_fields_hash, rt->mem_pool,
ret = nxt_http_fields_hash(&nxt_controller_fields_hash,
nxt_controller_request_fields,
nxt_nitems(nxt_controller_request_fields));

View File

@@ -186,16 +186,16 @@ static nxt_http_field_proc_t nxt_h1p_peer_fields[] = {
nxt_int_t
nxt_h1p_init(nxt_task_t *task, nxt_runtime_t *rt)
nxt_h1p_init(nxt_task_t *task)
{
nxt_int_t ret;
ret = nxt_http_fields_hash(&nxt_h1p_fields_hash, rt->mem_pool,
ret = nxt_http_fields_hash(&nxt_h1p_fields_hash,
nxt_h1p_fields, nxt_nitems(nxt_h1p_fields));
if (nxt_fast_path(ret == NXT_OK)) {
ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash,
rt->mem_pool, nxt_h1p_peer_fields,
nxt_h1p_peer_fields,
nxt_nitems(nxt_h1p_peer_fields));
}

View File

@@ -245,9 +245,9 @@ nxt_http_date(u_char *buf, struct tm *tm)
}
nxt_int_t nxt_http_init(nxt_task_t *task, nxt_runtime_t *rt);
nxt_int_t nxt_h1p_init(nxt_task_t *task, nxt_runtime_t *rt);
nxt_int_t nxt_http_response_hash_init(nxt_task_t *task, nxt_runtime_t *rt);
nxt_int_t nxt_http_init(nxt_task_t *task);
nxt_int_t nxt_h1p_init(nxt_task_t *task);
nxt_int_t nxt_http_response_hash_init(nxt_task_t *task);
void nxt_http_conn_init(nxt_task_t *task, void *obj, void *data);
nxt_http_request_t *nxt_http_request_create(nxt_task_t *task);

View File

@@ -22,8 +22,6 @@ static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp,
static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
static nxt_int_t nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
static void *nxt_http_field_hash_alloc(void *pool, size_t size);
static void nxt_http_field_hash_free(void *pool, void *p);
static nxt_int_t nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq,
void *data);
@@ -1133,8 +1131,8 @@ const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto nxt_aligned(64) = {
NXT_LVLHSH_BUCKET_SIZE(64),
{ NXT_HTTP_FIELD_LVLHSH_SHIFT, 0, 0, 0, 0, 0, 0, 0 },
nxt_http_field_hash_test,
nxt_http_field_hash_alloc,
nxt_http_field_hash_free,
nxt_lvlhsh_alloc,
nxt_lvlhsh_free,
};
@@ -1153,20 +1151,6 @@ nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
}
static void *
nxt_http_field_hash_alloc(void *pool, size_t size)
{
return nxt_mp_align(pool, size, size);
}
static void
nxt_http_field_hash_free(void *pool, void *p)
{
nxt_mp_free(pool, p);
}
static nxt_int_t
nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, void *data)
{
@@ -1175,7 +1159,7 @@ nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, void *data)
nxt_int_t
nxt_http_fields_hash(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_http_fields_hash(nxt_lvlhsh_t *hash,
nxt_http_field_proc_t items[], nxt_uint_t count)
{
u_char ch;
@@ -1187,7 +1171,6 @@ nxt_http_fields_hash(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
lhq.replace = 0;
lhq.proto = &nxt_http_fields_hash_proto;
lhq.pool = mp;
for (i = 0; i < count; i++) {
key = NXT_HTTP_FIELD_HASH_INIT;
@@ -1214,7 +1197,7 @@ nxt_http_fields_hash(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_uint_t
nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level)
{
u_char ch;
@@ -1229,7 +1212,6 @@ nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
lhq.replace = 0;
lhq.proto = &proto;
lhq.pool = mp;
mask = level ? (1 << NXT_HTTP_FIELD_LVLHSH_SHIFT) - 1 : 0xFFFF;

View File

@@ -102,9 +102,9 @@ nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp,
nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp,
nxt_buf_mem_t *b);
nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash,
nxt_http_field_proc_t items[], nxt_uint_t count);
nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, nxt_mp_t *mp,
nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level);
nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
void *ctx);

View File

@@ -36,17 +36,17 @@ nxt_time_string_t nxt_http_date_cache = {
nxt_int_t
nxt_http_init(nxt_task_t *task, nxt_runtime_t *rt)
nxt_http_init(nxt_task_t *task)
{
nxt_int_t ret;
ret = nxt_h1p_init(task, rt);
ret = nxt_h1p_init(task);
if (ret != NXT_OK) {
return ret;
}
return nxt_http_response_hash_init(task, rt);
return nxt_http_response_hash_init(task);
}

View File

@@ -34,9 +34,9 @@ static nxt_http_field_proc_t nxt_response_fields[] = {
nxt_int_t
nxt_http_response_hash_init(nxt_task_t *task, nxt_runtime_t *rt)
nxt_http_response_hash_init(nxt_task_t *task)
{
return nxt_http_fields_hash(&nxt_response_fields_hash, rt->mem_pool,
return nxt_http_fields_hash(&nxt_response_fields_hash,
nxt_response_fields, nxt_nitems(nxt_response_fields));
}

View File

@@ -303,7 +303,7 @@ nxt_router_start(nxt_task_t *task, void *data)
}
#endif
ret = nxt_http_init(task, rt);
ret = nxt_http_init(task);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}

View File

@@ -510,7 +510,7 @@ static nxt_str_t nxt_http_test_big_request = nxt_string(
nxt_int_t
nxt_http_parse_test(nxt_thread_t *thr)
{
nxt_mp_t *mp, *mp_temp;
nxt_mp_t *mp_temp;
nxt_int_t rc;
nxt_uint_t i, colls, lvl_colls;
nxt_lvlhsh_t hash;
@@ -519,12 +519,7 @@ nxt_http_parse_test(nxt_thread_t *thr)
nxt_thread_time_update(thr);
mp = nxt_mp_create(1024, 128, 256, 32);
if (mp == NULL) {
return NXT_ERROR;
}
rc = nxt_http_fields_hash(&nxt_http_test_fields_hash, mp,
rc = nxt_http_fields_hash(&nxt_http_test_fields_hash,
nxt_http_test_fields,
nxt_nitems(nxt_http_test_fields));
if (rc != NXT_OK) {
@@ -569,14 +564,14 @@ nxt_http_parse_test(nxt_thread_t *thr)
nxt_memzero(&hash, sizeof(nxt_lvlhsh_t));
colls = nxt_http_fields_hash_collisions(&hash, mp,
colls = nxt_http_fields_hash_collisions(&hash,
nxt_http_test_bench_fields,
nxt_nitems(nxt_http_test_bench_fields),
0);
nxt_memzero(&hash, sizeof(nxt_lvlhsh_t));
lvl_colls = nxt_http_fields_hash_collisions(&hash, mp,
lvl_colls = nxt_http_fields_hash_collisions(&hash,
nxt_http_test_bench_fields,
nxt_nitems(nxt_http_test_bench_fields),
1);
@@ -587,7 +582,7 @@ nxt_http_parse_test(nxt_thread_t *thr)
nxt_memzero(&hash, sizeof(nxt_lvlhsh_t));
rc = nxt_http_fields_hash(&hash, mp, nxt_http_test_bench_fields,
rc = nxt_http_fields_hash(&hash, nxt_http_test_bench_fields,
nxt_nitems(nxt_http_test_bench_fields));
if (rc != NXT_OK) {
return NXT_ERROR;
@@ -607,8 +602,6 @@ nxt_http_parse_test(nxt_thread_t *thr)
return NXT_ERROR;
}
nxt_mp_destroy(mp);
return NXT_OK;
}