<div dir="ltr">Hi all<div><br></div><div style>I have been seeing slow but steady socket leak in nginx ever since I upgraded from 1.0.5 to 1.2.6. I have my custom module in nginx which I was sure what was the leak. This is how I went about investigating:</div>
<div style>1. Configure nginx with one worker</div><div style>2. strace on the worker process, tracing read/readv/write/writev/close/shutdown calls</div><div style>3. Every now and then, for all the open fds (from ls -l /proc/<pid>/fd), check the socket that is not available in netstat -pane</div>
<div style>4. What I saw was, the leaking socket always had the last operation as writev which returned an error.</div><div style>5. Increased the nginx log level to info and verified that nginx was getting ECONNRESET or EPIPE on writev failure. Which was OK.</div>
<div style>6. Traced back in code to see how it is handled, the error translates to CHAIN_ERROR and eventually causes ngx_http_finalize_request to be called. This in turn calls ngx_http_terminate_request.</div><div style>
<br></div><div style>However, in this function, the request is not terminated if r->write_event_handler is set. This seems to be set if the request handler is a user module. I think the rationale for the check is, if there is a module who is handling the request, dont terminate yet, wait for a write event on the socket and then terminate it (which is why I thought it is setting r->write_event_handler to ngx_http_terminate_handler).</div>
<div style><br></div><div style>I tried to repro this w/ empty_gif_handler however, it sends header and body in one call to writev which I cant get to fail in my test environment. To reproduce the bug, if I replace the call to ngx_http_send_response with ngx_http_send_header and ngx_http_output_filter (as used by ngx_upstream or other modules which dont have the headers and body together), I could reproduce the leak. I have a client that sends a request and closes the socket immediately, nginx sees the error, prints the info log, and then it doesnt close the socket.</div>
<div style><br></div><div style>I have a small patch attached, the fix I did is basically saying that if there is a connection error, there is no point setting write_event_handler as there wont be any activity on the socket, so just terminate it immediately.</div>
<div style><br></div><div style>I could be very wrong in the understanding of the code flow. My patch just fixes this and I am not very sure if this is the right fix. Please let me know.</div><div style><br></div><div style>
I will try to add a testcase to reproduce this in the nginx test framework.</div><div style><br></div><div style>Thank you for your patience.</div><div style><br></div><div style>Regards</div><div style>+Fasih</div></div>