[PATCH] Fixing a segmentation fault when resolver and poll are used together
Ruslan Ermilov
ru at nginx.com
Wed Jan 23 08:13:41 UTC 2013
On Tue, Jan 22, 2013 at 02:56:34PM -0800, agentzh wrote:
> I've noticed a segmentation fault caught by Valgrind/Memcheck when
> using ngx_resolver and ngx_poll_module together with Nginx 1.2.6 on
> Linux x86_64 (and i386 too):
>
> ==25191== Jump to the invalid address stated on the next line
> ==25191== at 0x0: ???
> ==25191== by 0x42CC67: ngx_event_process_posted (ngx_event_posted.c:40)
> ==25191== by 0x42C7E7: ngx_process_events_and_timers (ngx_event.c:274)
> ==25191== by 0x434BCB: ngx_single_process_cycle (ngx_process_cycle.c:315)
> ==25191== by 0x416981: main (nginx.c:409)
> ==25191== Address 0x0 is not stack'd, malloc'd or (recently) free'd
> ==25191==
>
> It crashes on the following source line in src/event/ngx_event_posted.c:
>
> ev->handler(ev);
>
> The minimized config sample is as follows:
>
> events {
> use poll;
> }
>
> http {
> server {
> listen 8080;
>
> location /t {
> set $myserver nginx.org;
> proxy_pass http://$myserver/;
> resolver 127.0.0.1;
> }
> }
> }
>
> assuming that there's nothing listening on the local port 53.
>
> Basically, when POLLERR happens ngx_poll_module will generate both a
> write event and a read event for the current connection but there is
> no write event handler registered for the UDP connection created in
> ngx_resolver.c, thus leading to calling a NULL function pointer.
>
> The simplest fix (though maybe not the most reasonable) is to register
> an empty write event handler in ngx_resolver.c, as shown in the patch
> attached to this mail (already tested on my side).
>
> Best regards,
> -agentzh
First of all, thanks for catching the bug!
I propose one of these patches instead:
%%%
Index: src/event/modules/ngx_poll_module.c
===================================================================
--- src/event/modules/ngx_poll_module.c (revision 5013)
+++ src/event/modules/ngx_poll_module.c (working copy)
@@ -366,7 +366,13 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_ms
* active handler
*/
- revents |= POLLIN|POLLOUT;
+ if (c->read->active) {
+ revents |= POLLIN;
+ }
+
+ if (c->write->active) {
+ revents |= POLLOUT;
+ }
}
found = 0;
%%%
%%%
Index: src/event/modules/ngx_poll_module.c
===================================================================
--- src/event/modules/ngx_poll_module.c (revision 5013)
+++ src/event/modules/ngx_poll_module.c (working copy)
@@ -371,7 +371,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_ms
found = 0;
- if (revents & POLLIN) {
+ if ((revents & POLLIN) && c->read->active) {
found = 1;
ev = c->read;
@@ -388,7 +388,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_ms
ngx_locked_post_event(ev, queue);
}
- if (revents & POLLOUT) {
+ if ((revents & POLLOUT) && c->write->active) {
found = 1;
ev = c->write;
%%%
While the first patch looks more natural to me, the second patch is
in line with the ngx_epoll_process_events() code.
More information about the nginx-devel
mailing list