xenols/nginx-radius — pull request #2 by lexelby (2014-06-18 15:43:22+00:00)
Title: don't share radius client UDP socket between processes and threads

This worked great for me when I tested it out initially, but after running for a couple of days, authentication started to seriously lag. I saw this kind of thing in the log (hostnames redacted):

Jun 18 06:33:36 ____ nginx: [error] 26731#0: *41694 ngx_send_radius_request 0x1b7c3a0 while sending to client, client: 10.1.100.105, server: , request:
"GET / HTTP/1.1", host: "____"
Jun 18 06:33:36 ____ nginx: [] 26731#0: release_req_queue_node: 0x7f419a3e70a8, r: 0x1b7c3a0
Jun 18 06:33:36 ____ nginx: [] 26731#0: acquire_req_queue_node: 0x7f419a3ea8e0, r: 0x0
Jun 18 06:33:36 ____ nginx: [error] 26731#0: *41694 ngx_send_radius_request rs: 1, assign 0x1b7c3a0 to 0x7f419a3ea8e0, id: 1 while sending to client, cl
ient: 10.1.100.105, server: , request: "GET / HTTP/1.1", host: "____"
Jun 18 06:33:36 ____ nginx: [] 26732#0: radius_recv_request: active = 0, 0x7f419a3ea8e0, r: 0x0
Jun 18 06:33:36 ____ nginx: [] 26731#0: radius_recv_request: error recvfrom
Jun 18 06:33:36 ____ nginx: [error] 26731#0: radius_read_handler: request not found
Jun 18 06:33:36 ____ nginx: [error] 26732#0: radius_read_handler: request not found

The socket is created during server initialization, and then subprocesses (or threads, if configured) all make use of the same socket. Process 26731 sends a request, but both 26732 and 26731 try to read the response at the same time. 26732 wins the race, but it doesn't have the request in its list, so it gets confused. 26731 loses the race and gets an error from recvfrom, and it never gets the response, so we have to wait for a timeout.

The attached patch delays socket creation until the init_process or init_thread hook function is called. I could also do lazy initialization and create the socket if it hasn't already been created in radius_send_request, but this way seemed to me to make my intention more clear.

In testing, this fixed the lag I was seeing, and I no longer see 'request not found' errors.