BUG/MEDIUM: listeners: CLOEXEC flag is not correctly set

The CLOEXEC flag was set using a F_SETFL which can't work.
To set the CLOEXEC flag F_SETFD should be used, the problem is that it
needs a new call to fcntl() and it's on the path of every accept.

This flag was only needed in the case of the master, so the patch was
reverted and the flag set only in this case.

The bug was introduced by 0b3e849 ("MEDIUM: listeners: set O_CLOEXEC on
the accepted FDs").

No backport needed.
This commit is contained in:
William Lallemand 2018-11-27 12:02:39 +01:00 committed by Willy Tarreau
parent 4b58c80ee2
commit d913800a7d

View File

@ -544,7 +544,7 @@ void listener_accept(int fd)
/* with sockpair@ we don't want to do an accept */
if (unlikely(l->addr.ss_family == AF_CUST_SOCKPAIR)) {
if ((cfd = recv_fd_uxst(fd)) != -1)
fcntl(cfd, F_SETFL, O_NONBLOCK|O_CLOEXEC);
fcntl(cfd, F_SETFL, O_NONBLOCK);
} else
#ifdef USE_ACCEPT4
@ -552,12 +552,12 @@ void listener_accept(int fd)
* fallback to the legacy accept() + fcntl().
*/
if (unlikely(accept4_broken ||
((cfd = accept4(fd, (struct sockaddr *)&addr, &laddr, SOCK_NONBLOCK|SOCK_CLOEXEC)) == -1 &&
((cfd = accept4(fd, (struct sockaddr *)&addr, &laddr, SOCK_NONBLOCK)) == -1 &&
(errno == ENOSYS || errno == EINVAL || errno == EBADF) &&
(accept4_broken = 1))))
#endif
if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) != -1)
fcntl(cfd, F_SETFL, O_NONBLOCK|O_CLOEXEC);
fcntl(cfd, F_SETFL, O_NONBLOCK);
if (unlikely(cfd == -1)) {
switch (errno) {
@ -604,6 +604,10 @@ void listener_accept(int fd)
}
}
/* we don't want to leak the FD upon reload if it's in the master */
if (unlikely(master == 1))
fcntl(cfd, F_SETFD, FD_CLOEXEC);
if (unlikely(cfd >= global.maxsock)) {
send_log(p, LOG_EMERG,
"Proxy %s reached the configured maximum connection limit. Please check the global 'maxconn' value.\n",