From f6ae58f24256a339eec3b17699b10ab11482e6c1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 10 May 2011 08:39:14 -0400 Subject: s3-prefork: add support for multiple listning file descriptors Signed-off-by: Andreas Schneider --- source3/lib/server_prefork.c | 147 +++++++++++++++++++------------------------ source3/lib/server_prefork.h | 16 +++-- source3/printing/spoolssd.c | 16 +++-- 3 files changed, 84 insertions(+), 95 deletions(-) (limited to 'source3') diff --git a/source3/lib/server_prefork.c b/source3/lib/server_prefork.c index 958dc2655e..53b6d5c992 100644 --- a/source3/lib/server_prefork.c +++ b/source3/lib/server_prefork.c @@ -28,7 +28,9 @@ struct prefork_pool { - int listen_fd; + int listen_fd_size; + int *listen_fds; + int lock_fd; prefork_main_fn_t *main_fn; @@ -46,8 +48,8 @@ int prefork_pool_destructor(struct prefork_pool *pfp) return 0; } -bool prefork_create_pool(struct tevent_context *ev_ctx, - TALLOC_CTX *mem_ctx, int listen_fd, +bool prefork_create_pool(struct tevent_context *ev_ctx, TALLOC_CTX *mem_ctx, + int listen_fd_size, int *listen_fds, int min_children, int max_children, prefork_main_fn_t *main_fn, void *private_data, struct prefork_pool **pf_pool) @@ -64,7 +66,15 @@ bool prefork_create_pool(struct tevent_context *ev_ctx, DEBUG(1, ("Out of memory!\n")); return false; } - pfp->listen_fd = listen_fd; + pfp->listen_fd_size = listen_fd_size; + pfp->listen_fds = talloc_array(pfp, int, listen_fd_size); + if (!pfp->listen_fds) { + DEBUG(1, ("Out of memory!\n")); + return false; + } + for (i = 0; i < listen_fd_size; i++) { + pfp->listen_fds[i] = listen_fds[i]; + } pfp->main_fn = main_fn; pfp->private_data = private_data; @@ -102,7 +112,9 @@ bool prefork_create_pool(struct tevent_context *ev_ctx, pfp->pool[i].status = PF_WORKER_IDLE; ret = pfp->main_fn(ev_ctx, &pfp->pool[i], - pfp->listen_fd, pfp->lock_fd, + pfp->listen_fd_size, + pfp->listen_fds, + pfp->lock_fd, pfp->private_data); exit(ret); @@ -176,7 +188,9 @@ int prefork_add_children(struct tevent_context *ev_ctx, pfp->pool[i].status = PF_WORKER_IDLE; ret = pfp->main_fn(ev_ctx, &pfp->pool[i], - pfp->listen_fd, pfp->lock_fd, + pfp->listen_fd_size, + pfp->listen_fds, + pfp->lock_fd, pfp->private_data); pfp->pool[i].status = PF_WORKER_EXITING; @@ -515,69 +529,6 @@ done: return ret; } -/* returns: - * negative errno on error - * -2 if server commands to terminate - * 0 if all ok - * ERRNO on other errors - */ - -int prefork_wait_for_client(struct pf_worker_data *pf, - int lock_fd, int listen_fd, - struct sockaddr *addr, - socklen_t *addrlen, int *fd) -{ - int ret; - int sd = -1; - int err; - - ret = prefork_grab_lock(pf, lock_fd, -1); - if (ret != 0) { - return ret; - } - - err = 0; - do { - sd = accept(listen_fd, addr, addrlen); - - if (sd != -1) break; - - if (errno == EINTR) { - if (pf->cmds == PF_SRV_MSG_EXIT) { - err = -2; - } - } else { - err = errno; - } - - } while ((sd == -1) && (err == 0)); - - /* return lock now, even if the accept failed. - * if it takes more than 10 seconds we are in deep trouble */ - ret = prefork_release_lock(pf, lock_fd, 2); - if (ret != 0) { - /* we were unable to release the lock!! */ - DEBUG(0, ("Terminating due to fatal failure!\n")); - - /* Just exit we cannot hold the whole server, better to error - * on this one client and hope it was a transiet problem */ - err = -2; - } - - if (err != 0) { - if (sd != -1) { - close(sd); - sd = -1; - } - return err; - } - - pf->status = PF_WORKER_BUSY; - pf->num_clients++; - *fd = sd; - return 0; -} - /* ==== async code ==== */ #define PF_ASYNC_LOCK_GRAB 0x01 @@ -683,8 +634,10 @@ struct pf_listen_state { struct tevent_context *ev; struct pf_worker_data *pf; + int listen_fd_size; + int *listen_fds; + int lock_fd; - int listen_fd; struct sockaddr *addr; socklen_t *addrlen; @@ -703,7 +656,9 @@ static void prefork_listen_release_done(struct tevent_req *subreq); struct tevent_req *prefork_listen_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct pf_worker_data *pf, - int lock_fd, int listen_fd, + int listen_fd_size, + int *listen_fds, + int lock_fd, struct sockaddr *addr, socklen_t *addrlen) { @@ -718,7 +673,8 @@ struct tevent_req *prefork_listen_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->pf = pf; state->lock_fd = lock_fd; - state->listen_fd = listen_fd; + state->listen_fd_size = listen_fd_size; + state->listen_fds = listen_fds; state->addr = addr; state->addrlen = addrlen; state->accept_fd = -1; @@ -734,12 +690,21 @@ struct tevent_req *prefork_listen_send(TALLOC_CTX *mem_ctx, return req; } +struct pf_listen_ctx { + TALLOC_CTX *fde_ctx; + struct tevent_req *req; + int listen_fd; +}; + static void prefork_listen_lock_done(struct tevent_req *subreq) { struct tevent_req *req; struct pf_listen_state *state; + struct pf_listen_ctx *ctx; struct tevent_fd *fde; + TALLOC_CTX *fde_ctx; int ret; + int i; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct pf_listen_state); @@ -750,11 +715,28 @@ static void prefork_listen_lock_done(struct tevent_req *subreq) return; } + fde_ctx = talloc_new(state); + if (tevent_req_nomem(fde_ctx, req)) { + return; + } + /* next step, accept */ - fde = tevent_add_fd(state->ev, state, - state->listen_fd, TEVENT_FD_READ, - prefork_listen_accept_handler, req); - tevent_req_nomem(fde, req); + for (i = 0; i < state->listen_fd_size; i++) { + ctx = talloc(fde_ctx, struct pf_listen_ctx); + if (tevent_req_nomem(ctx, req)) { + return; + } + ctx->fde_ctx = fde_ctx; + ctx->req = req; + ctx->listen_fd = state->listen_fds[i]; + + fde = tevent_add_fd(state->ev, fde_ctx, + ctx->listen_fd, TEVENT_FD_READ, + prefork_listen_accept_handler, ctx); + if (tevent_req_nomem(fde, req)) { + return; + } + } } static void prefork_listen_accept_handler(struct tevent_context *ev, @@ -763,13 +745,14 @@ static void prefork_listen_accept_handler(struct tevent_context *ev, { struct pf_listen_state *state; struct tevent_req *req, *subreq; + struct pf_listen_ctx *ctx; int err = 0; int sd = -1; - req = talloc_get_type_abort(pvt, struct tevent_req); - state = tevent_req_data(req, struct pf_listen_state); + ctx = talloc_get_type_abort(pvt, struct pf_listen_ctx); + state = tevent_req_data(ctx->req, struct pf_listen_state); - sd = accept(state->listen_fd, state->addr, state->addrlen); + sd = accept(ctx->listen_fd, state->addr, state->addrlen); if (sd == -1) { if (errno == EINTR) { /* keep trying */ @@ -780,8 +763,10 @@ static void prefork_listen_accept_handler(struct tevent_context *ev, } - /* do not track the listen fd anymore */ - talloc_free(fde); + /* do not track the listen fds anymore */ + req = ctx->req; + talloc_free(ctx->fde_ctx); + ctx = NULL; if (err) { tevent_req_error(req, err); return; diff --git a/source3/lib/server_prefork.h b/source3/lib/server_prefork.h index 936ad8d5bd..6df2a41444 100644 --- a/source3/lib/server_prefork.h +++ b/source3/lib/server_prefork.h @@ -47,7 +47,8 @@ struct pf_worker_data { typedef int (prefork_main_fn_t)(struct tevent_context *ev, struct pf_worker_data *pf, - int listen_fd, + int listen_fd_size, + int *listen_fds, int lock_fd, void *private_data); @@ -56,8 +57,8 @@ struct prefork_pool; /* ==== Functions used by controlling process ==== */ -bool prefork_create_pool(struct tevent_context *ev_ctx, - TALLOC_CTX *mem_ctx, int listen_fd, +bool prefork_create_pool(struct tevent_context *ev_ctx, TALLOC_CTX *mem_ctx, + int listen_fd_size, int *listen_fds, int min_children, int max_children, prefork_main_fn_t *main_fn, void *private_data, struct prefork_pool **pf_pool); @@ -76,15 +77,12 @@ void prefork_send_signal_to_all(struct prefork_pool *pfp, int signal_num); /* ==== Functions used by children ==== */ -int prefork_wait_for_client(struct pf_worker_data *pf, - int lock_fd, int listen_fd, - struct sockaddr *addr, - socklen_t *addrlen, int *fd); - struct tevent_req *prefork_listen_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct pf_worker_data *pf, - int lock_fd, int listen_fd, + int listen_fd_size, + int *listen_fds, + int lock_fd, struct sockaddr *addr, socklen_t *addrlen); int prefork_listen_recv(struct tevent_req *req, int *fd); diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c index 0d5a49d9ea..25223c94c5 100644 --- a/source3/printing/spoolssd.c +++ b/source3/printing/spoolssd.c @@ -348,7 +348,8 @@ struct spoolss_children_data { struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; struct pf_worker_data *pf; - int listen_fd; + int listen_fd_size; + int *listen_fds; int lock_fd; bool listening; @@ -358,7 +359,9 @@ static void spoolss_next_client(void *pvt); static int spoolss_children_main(struct tevent_context *ev_ctx, struct pf_worker_data *pf, - int listen_fd, int lock_fd, + int listen_fd_size, + int *listen_fds, + int lock_fd, void *private_data) { struct messaging_context *msg_ctx = server_messaging_context(); @@ -379,7 +382,8 @@ static int spoolss_children_main(struct tevent_context *ev_ctx, data->ev_ctx = ev_ctx; data->msg_ctx = msg_ctx; data->lock_fd = lock_fd; - data->listen_fd = listen_fd; + data->listen_fd_size = listen_fd_size; + data->listen_fds = listen_fds; data->listening = false; /* loop until it is time to exit */ @@ -457,7 +461,9 @@ static void spoolss_next_client(void *pvt) next->addrlen = sizeof(next->sunaddr); req = prefork_listen_send(next, data->ev_ctx, data->pf, - data->lock_fd, data->listen_fd, + data->listen_fd_size, + data->listen_fds, + data->lock_fd, (struct sockaddr *)&next->sunaddr, &next->addrlen); if (!req) { @@ -712,7 +718,7 @@ void start_spoolssd(struct tevent_context *ev_ctx, /* start children before any more initialization is done */ - ok = prefork_create_pool(ev_ctx, ev_ctx, listen_fd, + ok = prefork_create_pool(ev_ctx, ev_ctx, 1, &listen_fd, spoolss_min_children, spoolss_max_children, &spoolss_children_main, NULL, -- cgit