# Terminate a connection after sending headers

**URL:** <https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829>\
**Category:** NGINX\
**Created:** [September 1, 2014, 11:26pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829 "2014-09-01T23:26:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [September 1, 2014, 11:26pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/1 "2014-09-01T23:26:39Z")

</div>

Hi all,

In the module I’m developing, I have the possibility of encountering an  
error after the response headers were already sent. As the headers were  
already sent (with status 200) the only way for me to signal the error  
to  
the client would be to close the connection. I tried calling  
ngx\_http\_finalize\_request with both NGX\_ERROR and NGX\_HTTP\_CLOSE and the  
connection is not closed.  
After debugging it, I found it has to do with the ‘if  
(mr-\>write\_event\_handler)’ in ngx\_http\_terminate\_request. I’m not sure  
what  
is the purpose of this if, but in my case write\_event\_handler has the  
value  
ngx\_http\_request\_empty\_handler, so the if evaluates to true and the  
connection is not terminated. When I forcefully change  
write\_event\_handler  
to NULL with GDB, I see the connection is closed as expected.  
I searched the code for ‘write\_event\_handler =’ and could not find a  
single  
place where this member gets a value of NULL (it always gets a pointer  
to  
some function).

Can anyone confirm if this is really a bug ? maybe the if should be  
updated  
to ‘if (mr-\>write\_event\_handler != ngx\_http\_request\_empty\_handler)’ ?

Thank you,

Eran

Posted at Nginx Forum:

> **[terminate a connection after sending headers](https://forum.nginx.org/read.php?2,253006,253006#msg-253006)**
>
> Hi all, In the module I'm developing, I have the possibility of encountering an error after the response headers were already sent. As the headers were already sent (with status 200) the only way for me to signal the error to the client would be to...

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 2, 2014, 3:09pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/2 "2014-09-02T15:09:55Z")

</div>

Hello!

On Mon, Sep 01, 2014 at 05:25:56PM -0400, erankor2 wrote:

> is the purpose of this if, but in my case write\_event\_handler has the value  
> ngx\_http\_request\_empty\_handler, so the if evaluates to true and the  
> connection is not terminated. When I forcefully change write\_event\_handler  
> to NULL with GDB, I see the connection is closed as expected.  
> I searched the code for ‘write\_event\_handler =’ and could not find a single  
> place where this member gets a value of NULL (it always gets a pointer to  
> some function).

The r-\>write\_event\_handler is set to NULL on initial creation of a  
request. If write\_event\_handler is not NULL during a request  
termination, nginx posts an event instead of freeing the request  
request directly (this is done to avoid use-after-free when  
processing posted subrequests). The request is still freed  
though.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 3, 2014, 4:10pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/3 "2014-09-03T16:10:30Z")

</div>

Maxim, thank you very much for your response.

To clarify - the problem is not about freeing the request (I don’t think  
there’s a resource leak here), the problem is that the connection is  
just  
left hanging until the client closes it / the server is restarted.  
It is true that write\_event\_handler gets initialized to zero when the  
request is allocated, but it is set to ngx\_http\_request\_empty\_handler  
before  
the first line of my code even runs. In ngx\_http\_core\_content\_phase  
there’s:

```
if (r->content_handler) {
    r->write_event_handler = ngx_http_request_empty_handler;
    ngx_http_finalize_request(r, r->content_handler(r));
    return NGX_OK;
}

```

where r-\>content\_handler is the entry point to my code. So, unless I  
explicitly reset it back to NULL (something that I never saw in any  
other  
nginx module) write\_event\_handler will not be null and the connection  
will  
be left hanging.

I forked some sample hello world module and modified it to reproduce the  
problem, please check it out here:

> <https://github.com/erankor/nginx-hello-world-module/blob/master/ngx_http_hello_world_module.c>

In that code, I’m sending the response headers and then trigger a timer  
for  
1 second. In the timer callback I close the request with NGX\_ERROR, but  
the  
connection remains active (I used a timer here since that’s the easiest  
solution to defer the execution, in my real project I’m performing  
asynchronous file I/O)

Thank you !

Eran

Posted at Nginx Forum:

> **[Re: terminate a connection after sending headers](https://forum.nginx.org/read.php?2,253006,253040#msg-253040)**
>
> Hi all, In the module I'm developing, I have the possibility of encountering an error after the response headers were already sent. As the headers were already sent (with status 200) the only way for me to signal the error to the client would be to...

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 4, 2014, 3:10am UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/4 "2014-09-04T03:10:38Z")

</div>

Hello!

On Wed, Sep 03, 2014 at 10:10:01AM -0400, erankor2 wrote:

> ```
> if (r->content_handler) {
> 
> ```
> 
> I forked some sample hello world module and modified it to reproduce the  
> problem, please check it out here:

> <https://github.com/erankor/nginx-hello-world-module/blob/master/ngx_http_hello_world_module.c>

> In that code, I’m sending the response headers and then trigger a timer for  
> 1 second. In the timer callback I close the request with NGX\_ERROR, but the  
> connection remains active (I used a timer here since that’s the easiest  
> solution to defer the execution, in my real project I’m performing  
> asynchronous file I/O)

The problem is that you use your own timer, and don’t run posted  
requests after it - but the request termination code relies on  
posted requests being run.

If you are using your own events, you should do processing similar  
to ngx\_http\_request\_handler(), see src/http/ngx\_http\_request.c.  
Notably, you have to call the ngx\_http\_run\_posted\_requests()  
function after the code which calls ngx\_http\_finalize\_request().

In this particular case, trivial fix is to do something like:

static void  
event\_callback(ngx\_event\_t \*ev)  
{

- 

```
  ngx_connection_t *c;
  ngx_http_request_t *r = (ngx_http_request_t *)ev->data;

```

- 

```
  c = r->connection;

```

- 

```
  ngx_http_finalize_request(r, NGX_ERROR);

```

- 
- 

```
  ngx_http_run_posted_requests(c);

```

}

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 5, 2014, 6:35am UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/5 "2014-09-05T06:35:58Z")

</div>

Hello!

On Thu, Sep 04, 2014 at 04:38:41PM -0400, erankor2 wrote:

> it myself.
> 
> So my questions are:
> 
> 1. Is there a simple rule that dictates when I should call  
> ngx\_http\_run\_posted\_requests and when I should not ?  
> I can work around the problem by doing something like ‘if called from the  
> aio callback call ngx\_http\_run\_posted\_requests’ otherwise, don’t call, but  
> that doesn’t feel like the correct solution.

You should call ngx\_http\_run\_posted\_requests() after low-level  
events. That is, there is no need to call it after http-related  
events, as ngx\_http\_run\_posted\_requests() will be called by  
ngx\_http\_request\_handler(). But if your own low-level events are  
triggered, like the timer in your code, it’s your responsibility  
to call ngx\_http\_request\_handler() after them.

> 1. A simpler solution that seems to work for me, is to call  
> ngx\_http\_run\_posted\_requests only when I see that r-\>main-\>count is one  
> (before finalize). But I don’t know if that solution makes any sense - is  
> there any relation between these posted\_requests and the request count ?

No, it doesn’t make sense to check r-\>main-\>count.

> My understanding (before reading your reply :)) was that whenever I do  
> something asynchronous I must increment the count, whenever I call  
> finalize\_request the count is decremented and once the count reaches zero  
> the request is terminated. So, what I’m missing is why the termination of  
> the request has to be deferred via posted requests - couldn’t  
> ngx\_http\_terminate\_request just close the request only when it sees the  
> count reached zero instead ?

Termination on errors which you are doing isn’t expected to wait  
for r-\>main-\>count to reach zero. It is expected to proactively  
stop all ongoing activity by executing cleanup handlers, and then  
free the request.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 4, 2014, 10:39pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/6 "2014-09-04T22:39:24Z")

</div>

Thank you very much Maxim ! this works !

However, I bumped into a new problem, I use 2 different types of  
asyncronous  
operations in my code - file I/O and http requests. When I call  
ngx\_http\_run\_posted\_requests from the aio callback it works well, but  
when I  
call it from the HTTP completion callback it actually makes the request  
hang.  
I can see that it calls ngx\_http\_upstream\_check\_broken\_connection in  
r-\>write\_event\_handler(r). I guess that in this case I should let  
ngx\_http\_run\_posted\_requests run from the upstream module instead of  
calling  
it myself.

So my questions are:

1. Is there a simple rule that dictates when I should call  
ngx\_http\_run\_posted\_requests and when I should not ?  
I can work around the problem by doing something like ‘if called from  
the  
aio callback call ngx\_http\_run\_posted\_requests’ otherwise, don’t call,  
but  
that doesn’t feel like the correct solution.
2. A simpler solution that seems to work for me, is to call  
ngx\_http\_run\_posted\_requests only when I see that r-\>main-\>count is one  
(before finalize). But I don’t know if that solution makes any sense -  
is  
there any relation between these posted\_requests and the request count ?  
My understanding (before reading your reply :)) was that whenever I do  
something asynchronous I must increment the count, whenever I call  
finalize\_request the count is decremented and once the count reaches  
zero  
the request is terminated. So, what I’m missing is why the termination  
of  
the request has to be deferred via posted requests - couldn’t  
ngx\_http\_terminate\_request just close the request only when it sees the  
count reached zero instead ?

Thanks again for all your help, I really appreciate it !

Eran

Posted at Nginx Forum:

> **[Re: terminate a connection after sending headers](https://forum.nginx.org/read.php?2,253006,253081#msg-253081)**
>
> Hi all, In the module I'm developing, I have the possibility of encountering an error after the response headers were already sent. As the headers were already sent (with status 200) the only way for me to signal the error to the client would be to...

---

<div class="post-metadata">

**Author:** ![erankor2](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/85f322/32.png) [@erankor2](https://www.ruby-forum.com/u/erankor2)\
**Post date:** [September 7, 2014, 10:50pm UTC](https://www.ruby-forum.com/t/terminate-a-connection-after-sending-headers/231829/7 "2014-09-07T22:50:01Z")

</div>

Thank you very much, Maxim.

I implemented the solution as you advised.

Eran

Posted at Nginx Forum:

> **[Re: terminate a connection after sending headers](https://forum.nginx.org/read.php?2,253006,253116#msg-253116)**
>
> Hi all, In the module I'm developing, I have the possibility of encountering an error after the response headers were already sent. As the headers were already sent (with status 200) the only way for me to signal the error to the client would be to...
