From b852ad044b98c0c574c3420956e153055d46136d Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Fri, 15 Sep 2017 07:09:23 +1200 Subject: [PATCH] source4/smbd: refactor the process model for prefork Refactor the process model code to allow the addition of a prefork process model. - Add a process context to contain process model specific state - Add a service details structure to allow service to indicate which process model options they can support. In the new code the services advertise the features they support to the process model. The process model context is plumbed through to allow the process model to keep track of the supported options, and any state the process model may require. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam --- file_server/file_server.c | 6 ++- source4/cldap_server/cldap_server.c | 7 ++- source4/dns_server/dns_server.c | 9 +++- source4/dsdb/dns/dns_update.c | 7 ++- source4/dsdb/kcc/kcc_service.c | 6 ++- source4/dsdb/repl/drepl_service.c | 7 ++- source4/echo_server/echo_server.c | 6 ++- source4/kdc/kdc-heimdal.c | 17 ++++++- source4/kdc/kdc-server.c | 3 +- source4/kdc/kdc-service-mit.c | 18 ++++++- source4/ldap_server/ldap_server.c | 23 ++++++--- source4/nbt_server/nbt_server.c | 6 ++- source4/ntp_signd/ntp_signd.c | 10 +++- source4/rpc_server/dcerpc_server.c | 56 +++++++++++++++------- source4/rpc_server/dcerpc_server.h | 3 +- source4/rpc_server/service_rpc.c | 15 +++++- source4/smb_server/service_smb.c | 18 +++++-- source4/smb_server/smb_server.c | 5 +- source4/smb_server/smb_server.h | 3 +- source4/smbd/process_model.h | 15 +++--- source4/smbd/process_single.c | 21 +++++--- source4/smbd/process_standard.c | 32 ++++++++----- source4/smbd/service.c | 11 ++++- source4/smbd/service.h | 18 +++++++ source4/smbd/service_named_pipe.c | 6 ++- source4/smbd/service_stream.c | 23 ++++++--- source4/smbd/service_stream.h | 1 + source4/smbd/service_task.c | 20 ++++---- source4/smbd/service_task.h | 1 + source4/torture/rpc/spoolss_notify.c | 7 ++- source4/web_server/web_server.c | 15 ++++-- source4/winbind/winbindd.c | 11 ++++- source4/wrepl_server/wrepl_in_connection.c | 10 ++-- source4/wrepl_server/wrepl_out_helpers.c | 4 +- source4/wrepl_server/wrepl_server.c | 7 ++- 35 files changed, 322 insertions(+), 105 deletions(-) diff --git a/file_server/file_server.c b/file_server/file_server.c index 83641f819f6..20fa5770f82 100644 --- a/file_server/file_server.c +++ b/file_server/file_server.c @@ -97,5 +97,9 @@ NTSTATUS server_service_s3fs_init(TALLOC_CTX *); NTSTATUS server_service_s3fs_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "s3fs", s3fs_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "s3fs", s3fs_task_init, &details); } diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c index 35a2b99e222..3f845c7e240 100644 --- a/source4/cldap_server/cldap_server.c +++ b/source4/cldap_server/cldap_server.c @@ -243,5 +243,10 @@ static void cldapd_task_init(struct task_server *task) */ NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "cldap", cldapd_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "cldap", cldapd_task_init, + &details); } diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index d4f5f27d0bb..6a90e3089f5 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -642,7 +642,8 @@ static NTSTATUS dns_add_socket(struct dns_server *dns, &dns_tcp_stream_ops, "ip", address, &port, lpcfg_socket_options(dns->task->lp_ctx), - dns_socket); + dns_socket, + dns->task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to %s:%u TCP - %s\n", address, port, nt_errstr(status))); @@ -929,5 +930,9 @@ static void dns_task_init(struct task_server *task) NTSTATUS server_service_dns_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "dns", dns_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true, + }; + return register_server_service(ctx, "dns", dns_task_init, &details); } diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c index ba8431a3d1d..10be7ce86fc 100644 --- a/source4/dsdb/dns/dns_update.c +++ b/source4/dsdb/dns/dns_update.c @@ -707,5 +707,10 @@ static void dnsupdate_task_init(struct task_server *task) */ NTSTATUS server_service_dnsupdate_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "dnsupdate", dnsupdate_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true, + }; + return register_server_service(ctx, "dnsupdate", dnsupdate_task_init, + &details); } diff --git a/source4/dsdb/kcc/kcc_service.c b/source4/dsdb/kcc/kcc_service.c index 946a8fef3ec..a5508aff1a5 100644 --- a/source4/dsdb/kcc/kcc_service.c +++ b/source4/dsdb/kcc/kcc_service.c @@ -347,5 +347,9 @@ static void kccsrv_task_init(struct task_server *task) */ NTSTATUS server_service_kcc_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "kcc", kccsrv_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "kcc", kccsrv_task_init, &details); } diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index 0951a0f0cc0..8f16a2efb75 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -528,5 +528,10 @@ static void dreplsrv_task_init(struct task_server *task) */ NTSTATUS server_service_drepl_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "drepl", dreplsrv_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true, + }; + return register_server_service(ctx, "drepl", dreplsrv_task_init, + &details); } diff --git a/source4/echo_server/echo_server.c b/source4/echo_server/echo_server.c index e6102322cc8..9a66211ebe8 100644 --- a/source4/echo_server/echo_server.c +++ b/source4/echo_server/echo_server.c @@ -343,5 +343,9 @@ static void echo_task_init(struct task_server *task) */ NTSTATUS server_service_echo_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "echo", echo_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "echo", echo_task_init, &details); } diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c index d5c721b6056..788959a737a 100644 --- a/source4/kdc/kdc-heimdal.c +++ b/source4/kdc/kdc-heimdal.c @@ -468,5 +468,20 @@ static void kdc_task_init(struct task_server *task) /* called at smbd startup - register ourselves as a server service */ NTSTATUS server_service_kdc_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "kdc", kdc_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + /* + * Need to prevent pre-forking on kdc. + * The task_init function is run on the master process only + * and the irpc process name is registered in it's event loop. + * The child worker processes initialise their event loops on + * fork, so are not listening for the irpc event. + * + * The master process does not wait on that event context + * the master process is responsible for managing the worker + * processes not performing work. + */ + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "kdc", kdc_task_init, &details); } diff --git a/source4/kdc/kdc-server.c b/source4/kdc/kdc-server.c index 13e338de445..00b5c745fec 100644 --- a/source4/kdc/kdc-server.c +++ b/source4/kdc/kdc-server.c @@ -578,7 +578,8 @@ NTSTATUS kdc_add_socket(struct kdc_server *kdc, &kdc_tcp_stream_ops, "ip", address, &port, lpcfg_socket_options(kdc->task->lp_ctx), - kdc_socket); + kdc_socket, + kdc->task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to %s:%u TCP - %s\n", address, port, nt_errstr(status))); diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c index 7febf158a01..d48b0328882 100644 --- a/source4/kdc/kdc-service-mit.c +++ b/source4/kdc/kdc-service-mit.c @@ -358,5 +358,21 @@ NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx); NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx) { - return register_server_service(mem_ctx, "kdc", mitkdc_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + /* + * Need to prevent pre-forking on kdc. + * The task_init function is run on the master process only + * and the irpc process name is registered in it's event loop. + * The child worker processes initialise their event loops on + * fork, so are not listening for the irpc event. + * + * The master process does not wait on that event context + * the master process is responsible for managing the worker + * processes not performing work. + */ + .inhibit_pre_fork = true + }; + return register_server_service(mem_ctx, "kdc", mitkdc_task_init, + &details); } diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 7730ff981ca..d12c4e70e02 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -1030,7 +1030,7 @@ static NTSTATUS add_socket(struct task_server *task, model_ops, &ldap_stream_nonpriv_ops, "ip", address, &port, lpcfg_socket_options(lp_ctx), - ldap_service); + ldap_service, task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n", address, port, nt_errstr(status))); @@ -1045,7 +1045,8 @@ static NTSTATUS add_socket(struct task_server *task, &ldap_stream_nonpriv_ops, "ip", address, &port, lpcfg_socket_options(lp_ctx), - ldap_service); + ldap_service, + task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n", address, port, nt_errstr(status))); @@ -1067,7 +1068,8 @@ static NTSTATUS add_socket(struct task_server *task, &ldap_stream_nonpriv_ops, "ip", address, &port, lpcfg_socket_options(lp_ctx), - ldap_service); + ldap_service, + task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n", address, port, nt_errstr(status))); @@ -1081,7 +1083,8 @@ static NTSTATUS add_socket(struct task_server *task, &ldap_stream_nonpriv_ops, "ip", address, &port, lpcfg_socket_options(lp_ctx), - ldap_service); + ldap_service, + task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n", address, port, nt_errstr(status))); @@ -1210,7 +1213,7 @@ static void ldapsrv_task_init(struct task_server *task) model_ops, &ldap_stream_nonpriv_ops, "unix", ldapi_path, NULL, lpcfg_socket_options(task->lp_ctx), - ldap_service); + ldap_service, task->process_context); talloc_free(ldapi_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s - %s\n", @@ -1241,7 +1244,8 @@ static void ldapsrv_task_init(struct task_server *task) model_ops, &ldap_stream_priv_ops, "unix", ldapi_path, NULL, lpcfg_socket_options(task->lp_ctx), - ldap_service); + ldap_service, + task->process_context); talloc_free(ldapi_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("ldapsrv failed to bind to %s - %s\n", @@ -1261,5 +1265,10 @@ failed: NTSTATUS server_service_ldap_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "ldap", ldapsrv_task_init); + struct service_details details = { + .inhibit_fork_on_accept = false, + .inhibit_pre_fork = false + }; + return register_server_service(ctx, "ldap", ldapsrv_task_init, + &details); } diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c index 2196bb045e9..834c72f5f7c 100644 --- a/source4/nbt_server/nbt_server.c +++ b/source4/nbt_server/nbt_server.c @@ -100,5 +100,9 @@ static void nbtd_task_init(struct task_server *task) */ NTSTATUS server_service_nbtd_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "nbt", nbtd_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "nbt", nbtd_task_init, &details); } diff --git a/source4/ntp_signd/ntp_signd.c b/source4/ntp_signd/ntp_signd.c index 7949dc2f3b0..0884d2f53b5 100644 --- a/source4/ntp_signd/ntp_signd.c +++ b/source4/ntp_signd/ntp_signd.c @@ -541,7 +541,8 @@ static void ntp_signd_task_init(struct task_server *task) &ntp_signd_stream_ops, "unix", address, NULL, lpcfg_socket_options(ntp_signd->task->lp_ctx), - ntp_signd); + ntp_signd, + ntp_signd->task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to %s - %s\n", address, nt_errstr(status))); @@ -554,5 +555,10 @@ static void ntp_signd_task_init(struct task_server *task) /* called at smbd startup - register ourselves as a server service */ NTSTATUS server_service_ntp_signd_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "ntp_signd", ntp_signd_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "ntp_signd", ntp_signd_task_init, + &details); } diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 6a985c5c63c..24eaa65459e 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -2870,7 +2870,9 @@ static const struct stream_server_ops dcesrv_stream_ops = { static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, - struct tevent_context *event_ctx, const struct model_ops *model_ops) + struct tevent_context *event_ctx, + const struct model_ops *model_ops, + void *process_context) { struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 1; @@ -2890,7 +2892,7 @@ static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, model_ops, &dcesrv_stream_ops, "unix", endpoint, &port, lpcfg_socket_options(lp_ctx), - dcesrv_sock); + dcesrv_sock, process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n", endpoint, nt_errstr(status))); @@ -2902,7 +2904,9 @@ static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, - struct tevent_context *event_ctx, const struct model_ops *model_ops) + struct tevent_context *event_ctx, + const struct model_ops *model_ops, + void *process_context) { struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 1; @@ -2944,7 +2948,7 @@ static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, model_ops, &dcesrv_stream_ops, "unix", full_path, &port, lpcfg_socket_options(lp_ctx), - dcesrv_sock); + dcesrv_sock, process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n", endpoint, full_path, nt_errstr(status))); @@ -2955,7 +2959,9 @@ static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, - struct tevent_context *event_ctx, const struct model_ops *model_ops) + struct tevent_context *event_ctx, + const struct model_ops *model_ops, + void *process_context) { struct dcesrv_socket_context *dcesrv_sock; NTSTATUS status; @@ -2977,7 +2983,7 @@ static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx, status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx, model_ops, &dcesrv_stream_ops, endpoint, - dcesrv_sock); + dcesrv_sock, process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n", endpoint, nt_errstr(status))); @@ -2990,9 +2996,12 @@ static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx, /* add a socket address to the list of events, one event per dcerpc endpoint */ -static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, - struct tevent_context *event_ctx, const struct model_ops *model_ops, - const char *address) +static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *e, + struct tevent_context *event_ctx, + const struct model_ops *model_ops, + const char *address, + void *process_context) { struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 0; @@ -3016,7 +3025,7 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct model_ops, &dcesrv_stream_ops, "ip", address, &port, lpcfg_socket_options(dce_ctx->lp_ctx), - dcesrv_sock); + dcesrv_sock, process_context); if (!NT_STATUS_IS_OK(status)) { struct dcesrv_if_list *iface; DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ", @@ -3055,7 +3064,9 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, - struct tevent_context *event_ctx, const struct model_ops *model_ops) + struct tevent_context *event_ctx, + const struct model_ops *model_ops, + void *process_context) { NTSTATUS status; @@ -3070,7 +3081,9 @@ static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, num_interfaces = iface_list_count(ifaces); for(i = 0; i < num_interfaces; i++) { const char *address = iface_list_n_ip(ifaces, i); - status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address); + status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, + model_ops, address, + process_context); NT_STATUS_NOT_OK_RETURN(status); } } else { @@ -3080,7 +3093,9 @@ static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, wcard = iface_list_wildcard(dce_ctx); NT_STATUS_HAVE_NO_MEMORY(wcard); for (i=0; wcard[i]; i++) { - status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]); + status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, + model_ops, wcard[i], + process_context); if (NT_STATUS_IS_OK(status)) { num_binds++; } @@ -3098,23 +3113,28 @@ NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, struct tevent_context *event_ctx, - const struct model_ops *model_ops) + const struct model_ops *model_ops, + void *process_context) { enum dcerpc_transport_t transport = dcerpc_binding_get_transport(e->ep_description); switch (transport) { case NCACN_UNIX_STREAM: - return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops); + return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, + model_ops, process_context); case NCALRPC: - return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops); + return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, + model_ops, process_context); case NCACN_IP_TCP: - return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops); + return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, + model_ops, process_context); case NCACN_NP: - return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops); + return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, + model_ops, process_context); default: return NT_STATUS_NOT_SUPPORTED; diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h index c038075e0dd..f2fb0f69434 100644 --- a/source4/rpc_server/dcerpc_server.h +++ b/source4/rpc_server/dcerpc_server.h @@ -467,7 +467,8 @@ NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx, struct loadparm_context *lp_ctx, struct dcesrv_endpoint *e, struct tevent_context *event_ctx, - const struct model_ops *model_ops); + const struct model_ops *model_ops, + void *process_context); /** * retrieve credentials from a dce_call diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c index 3ff9f6ff887..eb75184a05f 100644 --- a/source4/rpc_server/service_rpc.c +++ b/source4/rpc_server/service_rpc.c @@ -116,7 +116,7 @@ static void dcesrv_task_init(struct task_server *task) } status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx, - this_model_ops); + this_model_ops, task->process_context); if (!NT_STATUS_IS_OK(status)) { goto failed; } @@ -142,5 +142,16 @@ failed: NTSTATUS server_service_rpc_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "rpc", dcesrv_task_init); + struct service_details details = { + /* + * This is a SNOWFLAKE, but sadly one that we + * will have to keep for now. The RPC server + * code above overstamps the SINGLE process model + * most of the time, but we need to be in forking + * mode by defult to get a forking NETLOGON server + */ + .inhibit_fork_on_accept = false, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "rpc", dcesrv_task_init, &details); } diff --git a/source4/smb_server/service_smb.c b/source4/smb_server/service_smb.c index a607861d6e3..ddf24a994a8 100644 --- a/source4/smb_server/service_smb.c +++ b/source4/smb_server/service_smb.c @@ -60,7 +60,11 @@ static void smbsrv_task_init(struct task_server *task) */ for(i = 0; i < num_interfaces; i++) { const char *address = iface_list_n_ip(ifaces, i); - status = smbsrv_add_socket(task, task->event_ctx, task->lp_ctx, task->model_ops, address); + status = smbsrv_add_socket(task, task->event_ctx, + task->lp_ctx, + task->model_ops, + address, + task->process_context); if (!NT_STATUS_IS_OK(status)) goto failed; } } else { @@ -72,7 +76,11 @@ static void smbsrv_task_init(struct task_server *task) goto failed; } for (i=0; wcard[i]; i++) { - status = smbsrv_add_socket(task, task->event_ctx, task->lp_ctx, task->model_ops, wcard[i]); + status = smbsrv_add_socket(task, task->event_ctx, + task->lp_ctx, + task->model_ops, + wcard[i], + task->process_context); if (!NT_STATUS_IS_OK(status)) goto failed; } talloc_free(wcard); @@ -87,7 +95,11 @@ failed: /* called at smbd startup - register ourselves as a server service */ NTSTATUS server_service_smb_init(TALLOC_CTX *ctx) { + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; ntvfs_init(cmdline_lp_ctx); share_init(); - return register_server_service(ctx, "smb", smbsrv_task_init); + return register_server_service(ctx, "smb", smbsrv_task_init, &details); } diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 7e4c032ab4c..45641a4f2c9 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -179,7 +179,8 @@ _PUBLIC_ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx, struct tevent_context *event_context, struct loadparm_context *lp_ctx, const struct model_ops *model_ops, - const char *address) + const char *address, + void *process_context) { const char **ports = lpcfg_smb_ports(lp_ctx); int i; @@ -192,7 +193,7 @@ _PUBLIC_ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx, model_ops, &smb_stream_ops, "ip", address, &port, lpcfg_socket_options(lp_ctx), - NULL); + NULL, process_context); NT_STATUS_NOT_OK_RETURN(status); } diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 40af4a64bb3..5ddfe78a288 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -397,7 +397,8 @@ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx, struct tevent_context *event_context, struct loadparm_context *lp_ctx, const struct model_ops *model_ops, - const char *address); + const char *address, + void *process_context); struct loadparm_context; diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h index d7bf3c87c7b..656a7f2e29c 100644 --- a/source4/smbd/process_model.h +++ b/source4/smbd/process_model.h @@ -51,8 +51,8 @@ struct model_ops { void (*)(struct tevent_context *, struct loadparm_context *, struct socket_context *, - struct server_id , void *), - void *); + struct server_id , void *, void *), + void *, void *); /* function to create a task */ void (*new_task)(struct tevent_context *, @@ -60,13 +60,16 @@ struct model_ops { const char *service_name, void (*)(struct tevent_context *, struct loadparm_context *, struct server_id, - void *), + void *, void *), void *, - int); + const struct service_details*, + const int); /* function to terminate a connection or task */ - void (*terminate)(struct tevent_context *, struct loadparm_context *lp_ctx, - const char *reason); + void (*terminate)(struct tevent_context *, + struct loadparm_context *lp_ctx, + const char *reason, + void * process_context); /* function to set a title for the connection or task */ void (*set_title)(struct tevent_context *, const char *title); diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index 54169e9b0cc..1027415a555 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -44,8 +44,10 @@ static void single_accept_connection(struct tevent_context *ev, void (*new_conn)(struct tevent_context *, struct loadparm_context *, struct socket_context *, - struct server_id , void *), - void *private_data) + struct server_id, void *, + void *), + void *private_data, + void *process_context) { NTSTATUS status; struct socket_context *connected_socket; @@ -79,7 +81,8 @@ static void single_accept_connection(struct tevent_context *ev, * combination of pid/fd should be unique system-wide */ new_conn(ev, lp_ctx, connected_socket, - cluster_id(pid, socket_get_fd(connected_socket)), private_data); + cluster_id(pid, socket_get_fd(connected_socket)), private_data, + process_context); } /* @@ -88,8 +91,11 @@ static void single_accept_connection(struct tevent_context *ev, static void single_new_task(struct tevent_context *ev, struct loadparm_context *lp_ctx, const char *service_name, - void (*new_task)(struct tevent_context *, struct loadparm_context *, struct server_id, void *), + void (*new_task)(struct tevent_context *, + struct loadparm_context *, + struct server_id, void *, void *), void *private_data, + const struct service_details *service_details, int from_parent_fd) { pid_t pid = getpid(); @@ -105,12 +111,15 @@ static void single_new_task(struct tevent_context *ev, * Using the pid unaltered makes debugging of which process * owns the messaging socket easier. */ - new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data); + new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data, NULL); } /* called when a task goes down */ -static void single_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx, const char *reason) +static void single_terminate(struct tevent_context *ev, + struct loadparm_context *lp_ctx, + const char *reason, + void *process_context) { DEBUG(3,("single_terminate: reason[%s]\n",reason)); } diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index c6cbfc23eda..431134e03ca 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -222,13 +222,18 @@ static struct standard_child_state *setup_standard_child_pipe(struct tevent_cont /* called when a listening socket becomes readable. */ -static void standard_accept_connection(struct tevent_context *ev, - struct loadparm_context *lp_ctx, - struct socket_context *sock, - void (*new_conn)(struct tevent_context *, - struct loadparm_context *, struct socket_context *, - struct server_id , void *), - void *private_data) +static void standard_accept_connection( + struct tevent_context *ev, + struct loadparm_context *lp_ctx, + struct socket_context *sock, + void (*new_conn)(struct tevent_context *, + struct loadparm_context *, + struct socket_context *, + struct server_id, + void *, + void *), + void *private_data, + void *process_context) { NTSTATUS status; struct socket_context *sock2; @@ -340,7 +345,8 @@ static void standard_accept_connection(struct tevent_context *ev, talloc_free(s); /* setup this new connection. Cluster ID is PID based for this process model */ - new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data); + new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data, + NULL); /* we can't return to the top level here, as that event context is gone, so we now process events in the new event context until there are no @@ -357,8 +363,9 @@ static void standard_accept_connection(struct tevent_context *ev, static void standard_new_task(struct tevent_context *ev, struct loadparm_context *lp_ctx, const char *service_name, - void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *), + void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *), void *private_data, + const struct service_details *service_details, int new_from_parent_fd) { pid_t pid; @@ -438,11 +445,11 @@ static void standard_new_task(struct tevent_context *ev, setproctitle("task %s server_id[%d]", service_name, (int)pid); /* setup this new task. Cluster ID is PID based for this process model */ - new_task(ev, lp_ctx, cluster_id(pid, 0), private_data); + new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, NULL); /* we can't return to the top level here, as that event context is gone, so we now process events in the new event context until there are no - more to process */ + more to process */ tevent_loop_wait(ev); talloc_free(ev); @@ -452,7 +459,8 @@ static void standard_new_task(struct tevent_context *ev, /* called when a task goes down */ _NORETURN_ static void standard_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx, - const char *reason) + const char *reason, + void *process_context) { DEBUG(2,("standard_terminate: reason[%s]\n",reason)); diff --git a/source4/smbd/service.c b/source4/smbd/service.c index 61ed684d00f..9a77ca80b70 100644 --- a/source4/smbd/service.c +++ b/source4/smbd/service.c @@ -30,6 +30,7 @@ static struct registered_server { struct registered_server *next, *prev; const char *service_name; + struct service_details *service_details; void (*task_init)(struct task_server *); } *registered_servers; @@ -38,13 +39,17 @@ static struct registered_server { */ NTSTATUS register_server_service(TALLOC_CTX *ctx, const char *name, - void (*task_init)(struct task_server *)) + void (*task_init) (struct task_server *), + struct service_details *details) { struct registered_server *srv; srv = talloc(ctx, struct registered_server); NT_STATUS_HAVE_NO_MEMORY(srv); srv->service_name = name; srv->task_init = task_init; + srv->service_details = + talloc_memdup(ctx, details, sizeof(struct service_details)); + NT_STATUS_HAVE_NO_MEMORY(srv->service_details); DLIST_ADD_END(registered_servers, srv); return NT_STATUS_OK; } @@ -64,7 +69,9 @@ static NTSTATUS server_service_init(const char *name, if (strcasecmp(name, srv->service_name) == 0) { return task_server_startup(event_context, lp_ctx, srv->service_name, - model_ops, srv->task_init, + model_ops, + srv->task_init, + srv->service_details, from_parent_fd); } } diff --git a/source4/smbd/service.h b/source4/smbd/service.h index 23a9e6315b9..2d11f142aed 100644 --- a/source4/smbd/service.h +++ b/source4/smbd/service.h @@ -23,8 +23,26 @@ #ifndef __SERVICE_H__ #define __SERVICE_H__ + #include "smbd/service_stream.h" #include "smbd/service_task.h" + +struct service_details { + /* + * Prevent the standard process model from forking a new worker + * process when accepting a new connection. Do this when the service + * relies on shared state, or the over-head of forking would be a + * significant part of the response time + */ + bool inhibit_fork_on_accept; + /* + * Prevent the pre-fork process model from pre-forking any worker + * processes. In this mode pre-fork is equivalent to standard with + * inhibit_fork_on_accept set. + */ + bool inhibit_pre_fork; +}; + #include "smbd/service_proto.h" #endif /* __SERVICE_H__ */ diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c index c7e31bc4718..744f9421717 100644 --- a/source4/smbd/service_named_pipe.c +++ b/source4/smbd/service_named_pipe.c @@ -188,7 +188,8 @@ NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx, const struct model_ops *model_ops, const struct stream_server_ops *stream_ops, const char *pipe_name, - void *private_data) + void *private_data, + void *process_context) { char *dirname; struct named_pipe_socket *pipe_sock; @@ -248,7 +249,8 @@ NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx, pipe_sock->pipe_path, NULL, NULL, - pipe_sock); + pipe_sock, + process_context); if (!NT_STATUS_IS_OK(status)) { goto fail; } diff --git a/source4/smbd/service_stream.c b/source4/smbd/service_stream.c index 917a1876e07..3f4a04ccf84 100644 --- a/source4/smbd/service_stream.c +++ b/source4/smbd/service_stream.c @@ -44,6 +44,7 @@ struct stream_socket { const struct model_ops *model_ops; struct socket_context *sock; void *private_data; + void *process_context; }; @@ -55,6 +56,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char struct tevent_context *event_ctx = srv_conn->event.ctx; const struct model_ops *model_ops = srv_conn->model_ops; struct loadparm_context *lp_ctx = srv_conn->lp_ctx; + void *process_context = srv_conn->process_context; TALLOC_CTX *frame = NULL; if (!reason) reason = "unknown reason"; @@ -89,8 +91,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char srv_conn->event.fde = NULL; imessaging_cleanup(srv_conn->msg_ctx); TALLOC_FREE(srv_conn); - model_ops->terminate(event_ctx, lp_ctx, reason); - + model_ops->terminate(event_ctx, lp_ctx, reason, process_context); TALLOC_FREE(frame); } @@ -138,7 +139,8 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev, const struct stream_server_ops *stream_ops, struct imessaging_context *msg_ctx, void *private_data, - struct stream_connection **_srv_conn) + struct stream_connection **_srv_conn, + void *process_context) { struct stream_connection *srv_conn; @@ -154,6 +156,7 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev, srv_conn->event.ctx = ev; srv_conn->lp_ctx = lp_ctx; srv_conn->event.fde = NULL; + srv_conn->process_context = process_context; *_srv_conn = srv_conn; return NT_STATUS_OK; @@ -166,7 +169,9 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev, static void stream_new_connection(struct tevent_context *ev, struct loadparm_context *lp_ctx, struct socket_context *sock, - struct server_id server_id, void *private_data) + struct server_id server_id, + void *private_data, + void *process_context) { struct stream_socket *stream_socket = talloc_get_type(private_data, struct stream_socket); struct stream_connection *srv_conn; @@ -186,6 +191,7 @@ static void stream_new_connection(struct tevent_context *ev, srv_conn->ops = stream_socket->ops; srv_conn->event.ctx = ev; srv_conn->lp_ctx = lp_ctx; + srv_conn->process_context = process_context; if (!socket_check_access(sock, "smbd", lpcfg_hosts_allow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hosts_deny(NULL, lpcfg_default_service(lp_ctx)))) { stream_terminate_connection(srv_conn, "denied by access rules"); @@ -258,8 +264,9 @@ static void stream_accept_handler(struct tevent_context *ev, struct tevent_fd *f connection. When done, it calls stream_new_connection() with the newly created socket */ stream_socket->model_ops->accept_connection(ev, stream_socket->lp_ctx, - stream_socket->sock, - stream_new_connection, stream_socket); + stream_socket->sock, + stream_new_connection, stream_socket, + stream_socket->process_context); } /* @@ -279,7 +286,8 @@ NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx, const char *sock_addr, uint16_t *port, const char *socket_options, - void *private_data) + void *private_data, + void *process_context) { NTSTATUS status; struct stream_socket *stream_socket; @@ -385,6 +393,7 @@ NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx, stream_socket->ops = stream_ops; stream_socket->event_ctx = event_context; stream_socket->model_ops = model_ops; + stream_socket->process_context = process_context; return NT_STATUS_OK; } diff --git a/source4/smbd/service_stream.h b/source4/smbd/service_stream.h index a7d3def6eae..81bf2754beb 100644 --- a/source4/smbd/service_stream.h +++ b/source4/smbd/service_stream.h @@ -62,6 +62,7 @@ struct stream_connection { uint processing; const char *terminate; + void *process_context; }; diff --git a/source4/smbd/service_task.c b/source4/smbd/service_task.c index e0e98f644e1..1d33a43e919 100644 --- a/source4/smbd/service_task.c +++ b/source4/smbd/service_task.c @@ -50,8 +50,8 @@ void task_server_terminate(struct task_server *task, const char *reason, bool fa imessaging_cleanup(task->msg_ctx); - model_ops->terminate(event_ctx, task->lp_ctx, reason); - + model_ops->terminate(event_ctx, task->lp_ctx, reason, + task->process_context); /* don't free this above, it might contain the 'reason' being printed */ talloc_free(task); } @@ -67,9 +67,11 @@ struct task_state { called by the process model code when the new task starts up. This then calls the server specific startup code */ -static void task_server_callback(struct tevent_context *event_ctx, +static void task_server_callback(struct tevent_context *event_ctx, struct loadparm_context *lp_ctx, - struct server_id server_id, void *private_data) + struct server_id server_id, + void *private_data, + void *context) { struct task_state *state = talloc_get_type(private_data, struct task_state); struct task_server *task; @@ -81,6 +83,7 @@ static void task_server_callback(struct tevent_context *event_ctx, task->model_ops = state->model_ops; task->server_id = server_id; task->lp_ctx = lp_ctx; + task->process_context = context; task->msg_ctx = imessaging_init(task, task->lp_ctx, @@ -97,11 +100,12 @@ static void task_server_callback(struct tevent_context *event_ctx, /* startup a task based server */ -NTSTATUS task_server_startup(struct tevent_context *event_ctx, +NTSTATUS task_server_startup(struct tevent_context *event_ctx, struct loadparm_context *lp_ctx, - const char *service_name, - const struct model_ops *model_ops, + const char *service_name, + const struct model_ops *model_ops, void (*task_init)(struct task_server *), + const struct service_details *service_details, int from_parent_fd) { struct task_state *state; @@ -113,7 +117,7 @@ NTSTATUS task_server_startup(struct tevent_context *event_ctx, state->model_ops = model_ops; state->model_ops->new_task(event_ctx, lp_ctx, service_name, - task_server_callback, state, + task_server_callback, state, service_details, from_parent_fd); return NT_STATUS_OK; diff --git a/source4/smbd/service_task.h b/source4/smbd/service_task.h index ded4590daff..2499dc1ddaf 100644 --- a/source4/smbd/service_task.h +++ b/source4/smbd/service_task.h @@ -31,6 +31,7 @@ struct task_server { struct loadparm_context *lp_ctx; struct server_id server_id; void *private_data; + void *process_context; }; diff --git a/source4/torture/rpc/spoolss_notify.c b/source4/torture/rpc/spoolss_notify.c index bcae5f8b17b..dd9cd31e8c0 100644 --- a/source4/torture/rpc/spoolss_notify.c +++ b/source4/torture/rpc/spoolss_notify.c @@ -474,7 +474,9 @@ static bool test_start_dcerpc_server(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "unable to initialize process models"); - status = smbsrv_add_socket(tctx, event_ctx, tctx->lp_ctx, process_model_startup("single"), address); + status = smbsrv_add_socket(tctx, event_ctx, tctx->lp_ctx, + process_model_startup("single"), + address, NULL); torture_assert_ntstatus_ok(tctx, status, "starting smb server"); status = dcesrv_init_context(tctx, tctx->lp_ctx, endpoints, &dce_ctx); @@ -483,7 +485,8 @@ static bool test_start_dcerpc_server(struct torture_context *tctx, for (e=dce_ctx->endpoint_list;e;e=e->next) { status = dcesrv_add_ep(dce_ctx, tctx->lp_ctx, - e, tctx->ev, process_model_startup("single")); + e, tctx->ev, + process_model_startup("single"), NULL); torture_assert_ntstatus_ok(tctx, status, "unable listen on dcerpc endpoint server"); } diff --git a/source4/web_server/web_server.c b/source4/web_server/web_server.c index d854a298a9c..faf1bc65650 100644 --- a/source4/web_server/web_server.c +++ b/source4/web_server/web_server.c @@ -330,8 +330,10 @@ static void websrv_task_init(struct task_server *task) task->lp_ctx, model_ops, &web_stream_ops, "ip", address, - &port, lpcfg_socket_options(task->lp_ctx), - task); + &port, + lpcfg_socket_options(task->lp_ctx), + task, + task->process_context); if (!NT_STATUS_IS_OK(status)) goto failed; } @@ -350,7 +352,8 @@ static void websrv_task_init(struct task_server *task) &web_stream_ops, "ip", wcard[i], &port, lpcfg_socket_options(task->lp_ctx), - wdata); + wdata, + task->process_context); if (!NT_STATUS_IS_OK(status)) goto failed; } talloc_free(wcard); @@ -372,5 +375,9 @@ failed: /* called at smbd startup - register ourselves as a server service */ NTSTATUS server_service_web_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "web", websrv_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "web", websrv_task_init, &details); } diff --git a/source4/winbind/winbindd.c b/source4/winbind/winbindd.c index c8c0733b615..6aa04185378 100644 --- a/source4/winbind/winbindd.c +++ b/source4/winbind/winbindd.c @@ -90,9 +90,16 @@ NTSTATUS server_service_winbindd_init(TALLOC_CTX *); NTSTATUS server_service_winbindd_init(TALLOC_CTX *ctx) { - NTSTATUS status = register_server_service(ctx, "winbindd", winbindd_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true, + }; + + NTSTATUS status = register_server_service(ctx, "winbindd", + winbindd_task_init, &details); if (!NT_STATUS_IS_OK(status)) { return status; } - return register_server_service(ctx, "winbind", winbindd_task_init); + return register_server_service(ctx, "winbind", winbindd_task_init, + &details); } diff --git a/source4/wrepl_server/wrepl_in_connection.c b/source4/wrepl_server/wrepl_in_connection.c index b8e9a16dc21..4920aa0328f 100644 --- a/source4/wrepl_server/wrepl_in_connection.c +++ b/source4/wrepl_server/wrepl_in_connection.c @@ -347,7 +347,8 @@ static const struct stream_server_ops wreplsrv_stream_ops = { NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, uint32_t peer_assoc_ctx, struct tstream_context **stream, - struct wreplsrv_in_connection **_wrepl_in) + struct wreplsrv_in_connection **_wrepl_in, + void* process_context) { struct wreplsrv_service *service = partner->service; struct wreplsrv_in_connection *wrepl_in; @@ -379,7 +380,8 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, &wreplsrv_stream_ops, service->task->msg_ctx, wrepl_in, - &conn); + &conn, + process_context); NT_STATUS_NOT_OK_RETURN(status); /* @@ -461,7 +463,7 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadpar &wreplsrv_stream_ops, "ipv4", address, &port, lpcfg_socket_options(task->lp_ctx), - service); + service, task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n", address, port, nt_errstr(status))); @@ -473,7 +475,7 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadpar status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops, &wreplsrv_stream_ops, "ipv4", address, &port, lpcfg_socket_options(task->lp_ctx), - service); + service, task->process_context); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n", address, port, nt_errstr(status))); diff --git a/source4/wrepl_server/wrepl_out_helpers.c b/source4/wrepl_server/wrepl_out_helpers.c index 782e2f2908f..0e3f0a458ba 100644 --- a/source4/wrepl_server/wrepl_out_helpers.c +++ b/source4/wrepl_server/wrepl_out_helpers.c @@ -988,6 +988,7 @@ static NTSTATUS wreplsrv_push_notify_wait_update(struct wreplsrv_push_notify_sta { struct wreplsrv_in_connection *wrepl_in; struct tstream_context *stream; + void *process_context = NULL; NTSTATUS status; status = wrepl_request_recv(state->subreq, state, NULL); @@ -1011,10 +1012,11 @@ static NTSTATUS wreplsrv_push_notify_wait_update(struct wreplsrv_push_notify_sta * NOTE: stream will be stolen by * wreplsrv_in_connection_merge() */ + process_context = state->io->in.partner->service->task->process_context; status = wreplsrv_in_connection_merge(state->io->in.partner, state->wreplconn->assoc_ctx.peer_ctx, &stream, - &wrepl_in); + &wrepl_in, process_context); NT_STATUS_NOT_OK_RETURN(status); /* now we can free the wreplsrv_out_connection */ diff --git a/source4/wrepl_server/wrepl_server.c b/source4/wrepl_server/wrepl_server.c index dc28e23371e..bd2ae2660a0 100644 --- a/source4/wrepl_server/wrepl_server.c +++ b/source4/wrepl_server/wrepl_server.c @@ -508,5 +508,10 @@ static void wreplsrv_task_init(struct task_server *task) */ NTSTATUS server_service_wrepl_init(TALLOC_CTX *ctx) { - return register_server_service(ctx, "wrepl", wreplsrv_task_init); + struct service_details details = { + .inhibit_fork_on_accept = true, + .inhibit_pre_fork = true + }; + return register_server_service(ctx, "wrepl", wreplsrv_task_init, + &details); } -- 2.34.1