mirror of
https://github.com/samba-team/samba.git
synced 2025-02-24 13:57:43 +03:00
s3-prefork: Set up a SIGCHLD handler by default
We need to properly handle preforked children so it is better to just do that automatically. If the parent needs/wants to intercept SIGCHLD events it can set a callback that will be called by the prefork code once the internal cleanup function that checks all prefork children has been executed. Signed-off-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
parent
d36a8dc896
commit
1155280a48
@ -40,9 +40,15 @@ struct prefork_pool {
|
||||
struct pf_worker_data *pool;
|
||||
|
||||
int allowed_clients;
|
||||
|
||||
prefork_sigchld_fn_t *sigchld_fn;
|
||||
void *sigchld_data;
|
||||
};
|
||||
|
||||
int prefork_pool_destructor(struct prefork_pool *pfp)
|
||||
static bool prefork_setup_sigchld_handler(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp);
|
||||
|
||||
static int prefork_pool_destructor(struct prefork_pool *pfp)
|
||||
{
|
||||
munmap(pfp->pool, pfp->pool_size * sizeof(struct pf_worker_data));
|
||||
return 0;
|
||||
@ -60,8 +66,9 @@ bool prefork_create_pool(struct tevent_context *ev_ctx, TALLOC_CTX *mem_ctx,
|
||||
size_t data_size;
|
||||
int ret;
|
||||
int i;
|
||||
bool ok;
|
||||
|
||||
pfp = talloc(mem_ctx, struct prefork_pool);
|
||||
pfp = talloc_zero(mem_ctx, struct prefork_pool);
|
||||
if (!pfp) {
|
||||
DEBUG(1, ("Out of memory!\n"));
|
||||
return false;
|
||||
@ -124,6 +131,13 @@ bool prefork_create_pool(struct tevent_context *ev_ctx, TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
ok = prefork_setup_sigchld_handler(ev_ctx, pfp);
|
||||
if (!ok) {
|
||||
DEBUG(1, ("Failed to setup SIGCHLD Handler!\n"));
|
||||
talloc_free(pfp);
|
||||
return false;
|
||||
}
|
||||
|
||||
*pf_pool = pfp;
|
||||
return true;
|
||||
}
|
||||
@ -291,7 +305,7 @@ int prefork_count_active_children(struct prefork_pool *pfp, int *total)
|
||||
return a;
|
||||
}
|
||||
|
||||
void prefork_cleanup_loop(struct prefork_pool *pfp)
|
||||
static void prefork_cleanup_loop(struct prefork_pool *pfp)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
@ -361,6 +375,46 @@ void prefork_send_signal_to_all(struct prefork_pool *pfp, int signal_num)
|
||||
}
|
||||
}
|
||||
|
||||
static void prefork_sigchld_handler(struct tevent_context *ev_ctx,
|
||||
struct tevent_signal *se,
|
||||
int signum, int count,
|
||||
void *siginfo, void *pvt)
|
||||
{
|
||||
struct prefork_pool *pfp;
|
||||
|
||||
pfp = talloc_get_type_abort(pvt, struct prefork_pool);
|
||||
|
||||
/* run the cleanup function to make sure all dead children are
|
||||
* properly and timely retired. */
|
||||
prefork_cleanup_loop(pfp);
|
||||
|
||||
if (pfp->sigchld_fn) {
|
||||
pfp->sigchld_fn(ev_ctx, pfp, pfp->sigchld_data);
|
||||
}
|
||||
}
|
||||
|
||||
static bool prefork_setup_sigchld_handler(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(ev_ctx, pfp, SIGCHLD, 0,
|
||||
prefork_sigchld_handler, pfp);
|
||||
if (!se) {
|
||||
DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void prefork_set_sigchld_callback(struct prefork_pool *pfp,
|
||||
prefork_sigchld_fn_t *sigchld_fn,
|
||||
void *private_data)
|
||||
{
|
||||
pfp->sigchld_fn = sigchld_fn;
|
||||
pfp->sigchld_data = private_data;
|
||||
}
|
||||
|
||||
/* ==== Functions used by children ==== */
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "system/network.h"
|
||||
#include <tevent.h>
|
||||
|
||||
struct prefork_pool;
|
||||
|
||||
enum pf_worker_status {
|
||||
PF_WORKER_NONE = 0,
|
||||
PF_WORKER_IDLE,
|
||||
@ -76,8 +78,16 @@ typedef int (prefork_main_fn_t)(struct tevent_context *ev,
|
||||
int lock_fd,
|
||||
void *private_data);
|
||||
|
||||
struct prefork_pool;
|
||||
|
||||
/**
|
||||
* @brief Callback function for parents that also want to be called on sigchld
|
||||
*
|
||||
* @param ev_ctx The event context
|
||||
* @param pool The pool handler
|
||||
* @param private_data Data private to the parent
|
||||
*/
|
||||
typedef void (prefork_sigchld_fn_t)(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pool,
|
||||
void *private_data);
|
||||
|
||||
/* ==== Functions used by controlling process ==== */
|
||||
|
||||
@ -161,14 +171,6 @@ int prefork_retire_children(struct prefork_pool *pfp,
|
||||
*/
|
||||
int prefork_count_active_children(struct prefork_pool *pfp, int *total);
|
||||
|
||||
/**
|
||||
* @brief Perform cleanups, like waiting (WNOHANG) dead children.
|
||||
* MUST be called regularly from the parent main loop.
|
||||
*
|
||||
* @param pfp The pool.
|
||||
*/
|
||||
void prefork_cleanup_loop(struct prefork_pool *pfp);
|
||||
|
||||
/**
|
||||
* @brief Inform all children that they are allowed to accept 'max' clients
|
||||
* now. Use this when all children are already busy and more clients
|
||||
@ -200,6 +202,17 @@ void prefork_reset_allowed_clients(struct prefork_pool *pfp);
|
||||
*/
|
||||
void prefork_send_signal_to_all(struct prefork_pool *pfp, int signal_num);
|
||||
|
||||
/**
|
||||
* @brief Sets the SIGCHLD callback
|
||||
*
|
||||
* @param pfp The pool handler.
|
||||
* @param sigchld_fn The callback function (pass NULL to unset).
|
||||
* @param private_data Private data for the callback function.
|
||||
*/
|
||||
void prefork_set_sigchld_callback(struct prefork_pool *pfp,
|
||||
prefork_sigchld_fn_t *sigchld_fn,
|
||||
void *private_data);
|
||||
|
||||
/* ==== Functions used by children ==== */
|
||||
|
||||
/**
|
||||
|
@ -228,7 +228,7 @@ static bool spoolss_shutdown_cb(void *ptr)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Childrens */
|
||||
/* Children */
|
||||
|
||||
struct spoolss_chld_sig_hup_ctx {
|
||||
struct messaging_context *msg_ctx;
|
||||
@ -537,21 +537,21 @@ static void check_updater_child(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx,
|
||||
struct tevent_signal *se,
|
||||
int signum, int count,
|
||||
void *siginfo, void *pvt)
|
||||
static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp,
|
||||
struct timeval current_time);
|
||||
static void spoolssd_check_children(struct tevent_context *ev_ctx,
|
||||
struct tevent_timer *te,
|
||||
struct timeval current_time,
|
||||
void *pvt);
|
||||
|
||||
static void spoolssd_sigchld_handler(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp,
|
||||
void *private_data)
|
||||
{
|
||||
struct prefork_pool *pfp;
|
||||
int active, total;
|
||||
int n, r;
|
||||
|
||||
pfp = talloc_get_type_abort(pvt, struct prefork_pool);
|
||||
|
||||
/* run the cleanup function to make sure all dead children are
|
||||
* properly and timely retired. */
|
||||
prefork_cleanup_loop(pfp);
|
||||
|
||||
/* now check we do not descend below the minimum */
|
||||
active = prefork_count_active_children(pfp, &total);
|
||||
|
||||
@ -574,38 +574,13 @@ static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx,
|
||||
check_updater_child();
|
||||
}
|
||||
|
||||
static bool spoolssd_setup_sig_chld_handler(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp)
|
||||
{
|
||||
struct tevent_signal *se;
|
||||
|
||||
se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
|
||||
spoolssd_sig_chld_handler, pfp);
|
||||
if (!se) {
|
||||
DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp,
|
||||
struct timeval current_time);
|
||||
static void spoolssd_check_children(struct tevent_context *ev_ctx,
|
||||
struct tevent_timer *te,
|
||||
struct timeval current_time,
|
||||
void *pvt);
|
||||
|
||||
static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
|
||||
struct prefork_pool *pfp)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
ok = spoolssd_setup_sig_chld_handler(ev_ctx, pfp);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
/* add our oun sigchld callback */
|
||||
prefork_set_sigchld_callback(pfp, spoolssd_sigchld_handler, NULL);
|
||||
|
||||
ok = spoolssd_schedule_check(ev_ctx, pfp, tevent_timeval_current());
|
||||
return ok;
|
||||
|
Loading…
x
Reference in New Issue
Block a user