MINOR: fd: add a new "exported" flag and use it for all regular listeners
This new flag will be used to mark FDs that must be passed to any future
process across the CLI's "_getsocks" command.
The scheme here is quite complex and full of special cases:
- FDs inherited from parent processes are *not* exported this way, as
they are supposed to instead be passed by the master process itself
across reloads. However such FDs ought never to be paused otherwise
this would disrupt the socket in the parent process as well;
- FDs resulting from a "bind" performed over a socket pair, which are
in fact one side of a socket pair passed inside another control socket
pair must not be passed either. Since all of them are used the same
way, for now it's enough never to put this "exported" flag to FDs
bound by the socketpair code.
- FDs belonging to temporary listeners (e.g. a passive FTP data port)
must not be passed either. Fortunately we don't have such FDs yet.
- the rest of the listeners for now are made of TCP, UNIX stream, ABNS
sockets and are exportable, so they get the flag.
- UDP listeners were wrongly created as listeners and are not suitable
here. Their FDs should be passed but for now they are not since the
client doesn't even distinguish the SO_TYPE of the retrieved sockets.
In addition, it's important to keep in mind that:
- inherited FDs may never be closed in master process but may be closed
in worker processes if the service is shut down (useless since still
bound, but technically possible) ;
- inherited FDs may not be disabled ;
- exported FDs may be disabled because the caller will perform the
subsequent listen() on them. However that might not work for all OSes
- exported FDs may be closed, it just means the service was shut down
from the worker, and will be rebound in the new process. This implies
that we have to disable exported on close().
=> as such, contrary to an apparently obvious equivalence, the "exported"
status doesn't imply anything regarding the ability to close a
listener's FD or not.
diff --git a/include/haproxy/fd-t.h b/include/haproxy/fd-t.h
index 6ff8ef1..2b51125 100644
--- a/include/haproxy/fd-t.h
+++ b/include/haproxy/fd-t.h
@@ -134,6 +134,7 @@
unsigned char cloned:1; /* 1 if a cloned socket, requires EPOLL_CTL_DEL on close */
unsigned char initialized:1; /* 1 if init phase was done on this fd (e.g. set non-blocking) */
unsigned char et_possible:1; /* 1 if edge-triggered is possible on this FD */
+ unsigned char exported:1; /* 1 if the FD is exported and must not be closed */
#ifdef DEBUG_FD
unsigned int event_count; /* number of events reported */
#endif
diff --git a/include/haproxy/fd.h b/include/haproxy/fd.h
index 240842a..6f0401e 100644
--- a/include/haproxy/fd.h
+++ b/include/haproxy/fd.h
@@ -441,6 +441,7 @@
fdtab[fd].linger_risk = 0;
fdtab[fd].cloned = 0;
fdtab[fd].et_possible = 0;
+ fdtab[fd].exported = 0;
#ifdef DEBUG_FD
fdtab[fd].event_count = 0;
#endif
diff --git a/src/fd.c b/src/fd.c
index 86c2d43..c72dddd 100644
--- a/src/fd.c
+++ b/src/fd.c
@@ -329,6 +329,7 @@
fdinfo[fd].port_range = NULL;
fdtab[fd].owner = NULL;
fdtab[fd].thread_mask = 0;
+ fdtab[fd].exported = 0;
close(fd);
_HA_ATOMIC_SUB(&ha_used_fds, 1);
if (locked)
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 2f8ec22..98a6310 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1114,6 +1114,10 @@
fd_insert(fd, listener, listener->proto->accept,
thread_mask(listener->bind_conf->bind_thread) & all_threads_mask);
+ /* for now, all regularly bound TCP listeners are exportable */
+ if (!(listener->options & LI_O_INHERITED))
+ fdtab[fd].exported = 1;
+
tcp_return:
if (msg && errlen) {
char pn[INET6_ADDRSTRLEN];
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 586b119..2a4610f 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -352,6 +352,10 @@
fd_insert(fd, listener, listener->proto->accept,
thread_mask(listener->bind_conf->bind_thread) & all_threads_mask);
+ /* for now, all regularly bound UNIX listeners are exportable */
+ if (!(listener->options & LI_O_INHERITED))
+ fdtab[fd].exported = 1;
+
return err;
err_rename: