NGINX模块子请求回调中rc=NGX_AGAIN时的预期处理方式
NGINX子请求回调中
NGX_AGAIN且request->out=NULL的处理逻辑 我正在编写一个依赖子请求调用的NGINX模块,在回调函数中遇到了rc=NGX_AGAIN且request->out=NULL的情况,此时无法获取子请求的响应内容,想知道这种情况下回调函数的预期行为是什么?
子请求设置代码
/// Setup callback ngx_http_request_t *sub_request; ngx_http_post_subrequest_t *callback = ngx_pcalloc(request->pool, sizeof(ngx_http_post_subrequest_t)); callback->handler = callback_proc; callback->data = data; ngx_int_t result = ngx_http_subrequest(request, uri, NULL, &sub_request, callback, NGX_HTTP_SUBREQUEST_IN_MEMORY);
回调处理函数代码
static ngx_int_t callback_proc(ngx_http_request_t *request, void *data, ngx_int_t rc) { // unbox and sanity check data->value->len = r->out->buf->last - r->out->buf->pos; // <<-- SIGSEV because r->out is NULL data->value->data = r->out->buf->pos; return rc; }
核心结论
当回调函数收到NGX_AGAIN返回码时,意味着子请求尚未完成处理,此时request->out为NULL是正常现象,回调函数需要直接返回NGX_AGAIN,绝对不能尝试访问request->out相关的响应数据。
详细解释
NGX_AGAIN的含义:在NGINX子请求机制中,NGX_AGAIN表示子请求的IO操作仍在进行,响应内容还未生成完毕。此时触发回调只是通知你子请求处于处理中状态,而非已经完成。request->out为NULL的原因:只有当子请求完全处理完成(比如返回NGX_OK或其他表示完成的状态码)时,NGINX才会把响应内容填充到request->out链表中。子请求未完成时,这个字段自然为空。- 回调的正确行为:
- 直接返回
NGX_AGAIN,不做任何读取响应的操作,避免空指针访问导致崩溃(如你代码中出现的SIGSEGV)。 - 无需额外的清理或资源释放操作,NGINX会在子请求后续的处理流程中再次触发该回调,直到子请求完成。
- 直接返回
代码修复建议
修改回调函数,先判断返回码,仅当子请求完成后再处理响应数据:
static ngx_int_t callback_proc(ngx_http_request_t *r, void *data, ngx_int_t rc) { // 子请求未完成,直接返回 if (rc == NGX_AGAIN) { return rc; } // 子请求完成后,安全读取响应 if (r->out != NULL && r->out->buf != NULL) { data->value->len = r->out->buf->last - r->out->buf->pos; data->value->data = r->out->buf->pos; } return rc; }
内容的提问来源于stack exchange,提问作者dvhh
相关产品推荐
相关产品推荐

