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