mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r3356: in the standard process model we need to make sure we close all
listening sockets after the fork to prevent the child still listening
on incoming requests.
I have also added an optimisation where we use dup()/close() to lower
the file descriptor number of the new socket to the lowest possible
after closing our listening sockets. This keeps the max fd num passed
to select() low, which makes a difference to the speed of select().
(This used to be commit f2a9bbc317
)
This commit is contained in:
parent
bc24603e41
commit
0caeda53d3
@ -260,6 +260,28 @@ int socket_get_fd(struct socket_context *sock)
|
||||
return sock->ops->get_fd(sock);
|
||||
}
|
||||
|
||||
/*
|
||||
call dup() on a socket, and close the old fd. This is used to change
|
||||
the fd to the lowest available number, to make select() more
|
||||
efficient (select speed depends on the maxiumum fd number passed to
|
||||
it)
|
||||
*/
|
||||
NTSTATUS socket_dup(struct socket_context *sock)
|
||||
{
|
||||
int fd;
|
||||
if (sock->fd == -1) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
fd = dup(sock->fd);
|
||||
if (fd == -1) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
close(sock->fd);
|
||||
sock->fd = fd;
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type)
|
||||
{
|
||||
if (strcmp("ip", name) == 0 ||
|
||||
|
@ -34,7 +34,8 @@ static void standard_model_startup(void)
|
||||
/*
|
||||
called when a listening socket becomes readable
|
||||
*/
|
||||
static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde, time_t t, uint16_t flags)
|
||||
static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde,
|
||||
time_t t, uint16_t flags)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct socket_context *sock;
|
||||
@ -63,7 +64,11 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
|
||||
/* Child code ... */
|
||||
|
||||
/* close all the listening sockets */
|
||||
event_remove_fd_all_handler(ev, standard_accept_connection);
|
||||
service_close_listening_sockets(server_socket->service->srv_ctx);
|
||||
|
||||
/* we don't care if the dup fails, as its only a select()
|
||||
speed optimisation */
|
||||
socket_dup(sock);
|
||||
|
||||
/* tdb needs special fork handling */
|
||||
if (tdb_reopen_all() == -1) {
|
||||
|
@ -77,6 +77,8 @@ struct server_context *server_service_startup(const char *model)
|
||||
|
||||
/* TODO: service_init() should return a result */
|
||||
service->ops->service_init(service, model_ops);
|
||||
|
||||
DLIST_ADD(srv_ctx->service_list, service);
|
||||
}
|
||||
|
||||
return srv_ctx;
|
||||
@ -328,3 +330,22 @@ BOOL server_service_init(void)
|
||||
DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION));
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
close all listening sockets. This is called by process models that fork, to
|
||||
ensure that the listen sockets from the parent are closed
|
||||
*/
|
||||
void service_close_listening_sockets(struct server_context *srv_ctx)
|
||||
{
|
||||
struct server_service *svc;
|
||||
for (svc=srv_ctx->service_list;svc;svc=svc->next) {
|
||||
struct server_socket *sock;
|
||||
for (sock=svc->socket_list;sock;sock=sock->next) {
|
||||
event_remove_fd(sock->event.ctx, sock->event.fde);
|
||||
sock->event.fde = NULL;
|
||||
socket_destroy(sock->socket);
|
||||
sock->socket = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user