/* functions acting on the receiver */
void (*rx_enable)(struct receiver *rx); /* enable receiving on the receiver */
void (*rx_disable)(struct receiver *rx); /* disable receiving on the receiver */
+ void (*rx_unbind)(struct receiver *rx); /* unbind the receiver, most often closing the FD */
int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */
int (*rx_resume)(struct receiver *rx); /* try to resume a temporarily suspended receiver */
int sock_create_server_socket(struct connection *conn);
void sock_enable(struct receiver *rx);
void sock_disable(struct receiver *rx);
+void sock_unbind(struct receiver *rx);
int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
int sock_get_old_sockets(const char *unixsocket);
* LI_ASSIGNED state, except if the FD is not closed, in which case it may
* remain in LI_LISTEN. Depending on the process' status (master or worker),
* the listener's bind options and the receiver's origin, it may or may not
- * close the receiver's FD. Must be called with the lock held.
+ * close the receiver's FD, according to what is provided at the receiver
+ * level. Must be called with the lock held.
*/
void do_unbind_listener(struct listener *listener)
{
goto out_close;
}
- if (listener->state >= LI_PAUSED) {
- if (listener->state >= LI_READY) {
- listener->rx.proto->disable(listener);
+ if (listener->state >= LI_READY) {
+ listener->rx.proto->disable(listener);
+ if (listener->rx.flags & RX_F_BOUND)
listener_set_state(listener, LI_LISTEN);
- }
- listener->rx.proto->rx_disable(&listener->rx);
}
out_close:
- /* There are a number of situations where we prefer to keep the FD and
- * not to close it (unless we're stopping, of course):
- * - worker process unbinding from a worker's FD with socket transfer enabled => keep
- * - master process unbinding from a master's inherited FD => keep
- * - master process unbinding from a master's FD => close
- * - master process unbinding from a worker's FD => close
- * - worker process unbinding from a master's FD => close
- * - worker process unbinding from a worker's FD => close
- */
-
- if (!stopping && !master &&
- !(listener->rx.flags & RX_F_MWORKER) &&
- (global.tune.options & GTUNE_SOCKET_TRANSFER))
- return;
-
- if (!stopping && master &&
- listener->rx.flags & RX_F_MWORKER &&
- listener->rx.flags & RX_F_INHERITED)
- return;
+ if (listener->rx.flags & RX_F_BOUND)
+ listener->rx.proto->rx_unbind(&listener->rx);
- listener->rx.flags &= ~RX_F_BOUND;
- if (listener->rx.fd != -1)
- fd_delete(listener->rx.fd);
- listener->rx.fd = -1;
- if (listener->state > LI_ASSIGNED)
+ /* we may have to downgrade the listener if the rx was closed */
+ if (!(listener->rx.flags & RX_F_BOUND) && listener->state > LI_ASSIGNED)
listener_set_state(listener, LI_ASSIGNED);
}
.listen = sockpair_bind_listener,
.enable = sockpair_enable_listener,
.disable = sockpair_disable_listener,
+ .rx_unbind = sock_unbind,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
.accept = &listener_accept,
.disable = tcp_disable_listener,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
+ .rx_unbind = sock_unbind,
.rx_suspend = tcp_suspend_receiver,
.rx_resume = tcp_resume_receiver,
.accept = &listener_accept,
.disable = tcp_disable_listener,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
+ .rx_unbind = sock_unbind,
.rx_suspend = tcp_suspend_receiver,
.rx_resume = tcp_resume_receiver,
.accept = &listener_accept,
.disable = udp_disable_listener,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
+ .rx_unbind = sock_unbind,
.rx_suspend = udp_suspend_receiver,
.rx_resume = udp_resume_receiver,
.receivers = LIST_HEAD_INIT(proto_udp4.receivers),
.disable = udp_disable_listener,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
+ .rx_unbind = sock_unbind,
.rx_suspend = udp_suspend_receiver,
.rx_resume = udp_resume_receiver,
.receivers = LIST_HEAD_INIT(proto_udp6.receivers),
.disable = uxst_disable_listener,
.rx_enable = sock_enable,
.rx_disable = sock_disable,
+ .rx_unbind = sock_unbind,
.rx_suspend = uxst_suspend_receiver,
.accept = &listener_accept,
.connect = &uxst_connect_server,
fd_stop_recv(rx->fd);
}
+/* stops, unbinds and possibly closes the FD associated with receiver rx */
+void sock_unbind(struct receiver *rx)
+{
+ /* There are a number of situations where we prefer to keep the FD and
+ * not to close it (unless we're stopping, of course):
+ * - worker process unbinding from a worker's FD with socket transfer enabled => keep
+ * - master process unbinding from a master's inherited FD => keep
+ * - master process unbinding from a master's FD => close
+ * - master process unbinding from a worker's FD => close
+ * - worker process unbinding from a master's FD => close
+ * - worker process unbinding from a worker's FD => close
+ */
+ if (rx->flags & RX_F_BOUND)
+ rx->proto->rx_disable(rx);
+
+ if (!stopping && !master &&
+ !(rx->flags & RX_F_MWORKER) &&
+ (global.tune.options & GTUNE_SOCKET_TRANSFER))
+ return;
+
+ if (!stopping && master &&
+ rx->flags & RX_F_MWORKER &&
+ rx->flags & RX_F_INHERITED)
+ return;
+
+ rx->flags &= ~RX_F_BOUND;
+ if (rx->fd != -1)
+ fd_delete(rx->fd);
+ rx->fd = -1;
+}
+
/*
* Retrieves the source address for the socket <fd>, with <dir> indicating
* if we're a listener (=0) or an initiator (!=0). It returns 0 in case of