nginx + my module crashes only when ignore client abort = on
gadh
nginx-forum at nginx.us
Sun Mar 17 09:47:24 UTC 2013
Ok, i'll attach my calling to subrequest code, its working flawlessly except
the case i reported here:
//------------------------------------------------------------------
/*
Note: the purspose of this code is to call a handler module (at rewrite
phase), send special POST subrequest to another server (independant of the
main request), wait with the module untill subrequest finishes, process its
data , then continue to backend or next handler module
*/
// the subrequest will call this handler after it finishes
ngx_int_t ngx_aaa_post_subrequest_handler (ngx_http_request_t *r, void
*data, ngx_int_t rc)
{
ngx_aaa_ctx_t *ctx = (ngx_aaa_ctx_t*)data;
ngx_chain_t *bufs;
ngx_uint_t status;
if (rc != NGX_OK)
{
NGX_aaa_LOG_ERROR("bad response (nginx code %d)",rc);
ctx->post.error = 1;
aaa_SUB_PROF_END
ngx_http_core_run_phases(r->main); // continue main request
return NGX_OK; //cannot return rc if != NGX_OK - see below
}
if (r->upstream) // when sending to another server, then subrequest is
passed on upstream module
{
bufs = r->upstream->out_bufs;
status = r->upstream->state->status;
}
else // runs on the same nginx, another port
{
NGX_aaa_LOG_ERROR("response could not get by 'upstream' method.
aborting");
ctx->post.error = 1;
aaa_SUB_PROF_END
ngx_http_core_run_phases(r->main);
return NGX_OK;
}
if (status != NGX_HTTP_OK) // == 200 OK
{
NGX_aaa_LOG_ERROR("bad response status (%d)",status);
ctx->post.error = 1;
aaa_SUB_PROF_END
ngx_http_core_run_phases(r->main);
return NGX_OK; // when returning error in subrequest, the nginx loops over
it untill ok, or after 2 loops its stucks the main req.
}
ctx->post.done = 1;
ctx->post.response_data = ngx_aaa_utils_get_data_from_bufs(r, bufs);
ctx->post.response_handler(r, data); // passing ctx->post->response_data
to ngx_aaa_response_handler() - data parsing
if (!ctx->post.response_data)
ngx_http_core_run_phases(r->main);
if (!ctx->standalone)
ngx_http_core_run_phases(r->main); // release main request from its
wait and send it to the backend server
return NGX_OK;
}
// main code of calling to subrequest
ngx_int_t ngx_aaa_send_post_subrequest(ngx_http_request_t *r, ngx_aaa_ctx_t
*ctx, char *_uri, ngx_str_t *data, ngx_uint_t is_ret)
{
ngx_http_request_t *sr;
ngx_uint_t flags = 0;
ngx_http_post_subrequest_t *psr;
ngx_str_t uri;
ngx_int_t res;
ngx_buf_t *buf;
flags = NGX_HTTP_SUBREQUEST_IN_MEMORY;
uri.data = (u_char*)_uri;
uri.len = strlen(_uri);
psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
if (!psr)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
ctx->done = 0;
ctx->post.done = 0;
ctx->post.start = 1;
if (is_ret) // return answer to caller, async
{
psr->handler = ngx_aaa_post_subrequest_handler; // register callback
function for returning ans from the other end
psr->data = ctx;
}
else
psr = NULL;
// this func only registers the subreq in queue, but not activates it yet
// note: sr->request_body is nulled during this func, alloc later
res = ngx_http_subrequest(r, &uri, NULL , &sr, psr, flags);
if (res)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
ngx_memzero(&sr->headers_in, sizeof(sr->headers_in));
buf = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (!buf)
return NGX_ERROR;
// args is an ngx_str_t with the body
sr->method = NGX_HTTP_POST;
ngx_memcpy(&(sr->method_name), &ngx_aaa_post_method_name,
sizeof(ngx_str_t));
buf->temporary = 1;
buf->pos = data->data;
buf->last = buf->pos + data->len;
// do not inherit rb from parent
sr->request_body = ngx_palloc(r->pool, sizeof(ngx_http_request_body_t));
NGX_aaa_CHECK_ALLOC_AND_RETURN(sr->request_body)
// note: always alloc bufs even if ptr is lid - since its garbage from
former request ! (caused seg fault in mod_proxy !)
sr->request_body->bufs = ngx_alloc_chain_link(r->pool);
NGX_aaa_CHECK_ALLOC_AND_RETURN(sr->request_body->bufs)
// post body - re-populate , do not inherit from parent
sr->request_body->bufs->buf = buf;
sr->request_body->bufs->next = NULL;
sr->request_body->buf = buf;
sr->header_in = NULL;
buf->last_in_chain = 1;
buf->last_buf = 1;
sr->request_body_in_single_buf = 1;
sr->headers_in.content_length_n = ngx_buf_size(buf);
ngx_str_t c_len_key = ngx_string("Content-Length");
ngx_str_t c_len_l;
char len_str[20];
sprintf(len_str, "%lu", ngx_buf_size(buf));
c_len_l.data = (u_char*)len_str;
c_len_l.len = strlen(len_str);
ngx_aaa_set_input_header(sr, &sr->headers_in.content_length, &c_len_key,
&c_len_l);
ngx_str_t key, l;
ngx_str_set(&key,"Content-Type");
ngx_str_set(&l, "application/x-www-form-urlencoded");
ngx_aaa_set_input_header(sr, &sr->headers_in.content_type, &key, &l);
return NGX_OK;
}
// handler module main function - calls the subrequest, waits for it to
finish
ngx_int_t ngx_aaa_handler(ngx_http_request_t *r)
{
// pseudo code: alloc module ctx - only once
if (ctx->post.start)
{
// check if post subrequest has ended - then call next module handler
if (ctx->post.done)
{
return NGX_DECLINED; // declined - if hdl is reg. in rewrite phase
}
else // wait for post subrequest to finish unless error
{
if (ctx->post.error)
{
return NGX_DECLINED; // subrequest finished - call next handler module
}
else
{
return NGX_AGAIN; // wait untill finish response to our subrequest
}
}
}
// prepare subrequest
// ngx_str - post body for the subrequest
ctx->post.response_handler = ngx_aaa_response_handler; // for subrequest
response data parsing
rc = ngx_aaa_send_post_subrequest(r, ctx, url, ngx_str, 1);
if (rc != NGX_OK)
{
NGX_aaa_LOG_ERROR("ngx_aaa_send_post_subrequest failed (error
%d)",rc);
return NGX_DECLINED;
}
/* NGX_DECLINED == pass to next handler, do not wait.
* NGX_OK == wait for subrequest to finish first (non blocking, of
course)
*/
return NGX_OK;
}
//------------------------------------------------------------------
i'de appreciate your help,
BTW, is there any "nginx subrequest coding guide" documentation available ?
its very confusing and lacks much info on the web, i got it working only
thru alot of trial-and-error.
Tnx
Gad
Posted at Nginx Forum: http://forum.nginx.org/read.php?2,237362,237454#msg-237454
More information about the nginx
mailing list