From e9a589feac531379e569bc39d803b16179002cfa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 2009 18:05:55 -0700 Subject: s4-server: kill main daemon if a task fails to initialise When one of our core tasks fails to initialise it can now ask for the server as a whole to die, rather than limping along in a degraded state. --- source4/cldap_server/cldap_server.c | 14 ++++++----- source4/dsdb/kcc/kcc_periodic.c | 2 +- source4/dsdb/kcc/kcc_service.c | 19 ++++++++------- source4/dsdb/repl/drepl_notify.c | 2 +- source4/dsdb/repl/drepl_periodic.c | 2 +- source4/dsdb/repl/drepl_service.c | 18 ++++++++------ source4/kdc/kdc.c | 28 ++++++++++----------- source4/ldap_server/ldap_server.c | 10 +++++--- source4/lib/messaging/irpc.h | 1 + source4/lib/messaging/messaging.h | 3 +++ source4/librpc/idl/irpc.idl | 7 ++++++ source4/nbt_server/irpc.c | 8 +++--- source4/nbt_server/nbt_server.c | 10 ++++---- source4/ntp_signd/ntp_signd.c | 6 ++--- source4/rpc_server/service_rpc.c | 2 +- source4/smb_server/smb_samba3.c | 2 +- source4/smb_server/smb_server.c | 2 +- source4/smbd/process_single.c | 4 ++- source4/smbd/server.c | 46 +++++++++++++++++++++++++++++++++++ source4/smbd/service_named_pipe.c | 2 ++ source4/smbd/service_task.c | 18 ++++++++++++-- source4/web_server/web_server.c | 2 +- source4/winbind/wb_server.c | 16 ++++++------ source4/wrepl_server/wrepl_periodic.c | 2 +- source4/wrepl_server/wrepl_server.c | 10 ++++---- 25 files changed, 159 insertions(+), 77 deletions(-) diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c index 1a08cd21f9..ee8c76ef2c 100644 --- a/source4/cldap_server/cldap_server.c +++ b/source4/cldap_server/cldap_server.c @@ -187,16 +187,18 @@ static void cldapd_task_init(struct task_server *task) load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); if (iface_count(ifaces) == 0) { - task_server_terminate(task, "cldapd: no network interfaces configured"); + task_server_terminate(task, "cldapd: no network interfaces configured", false); return; } switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: - task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration"); + task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration", + false); return; case ROLE_DOMAIN_MEMBER: - task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration"); + task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration", + false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want an CLDAP server */ @@ -207,21 +209,21 @@ static void cldapd_task_init(struct task_server *task) cldapd = talloc(task, struct cldapd_server); if (cldapd == NULL) { - task_server_terminate(task, "cldapd: out of memory"); + task_server_terminate(task, "cldapd: out of memory", true); return; } cldapd->task = task; cldapd->samctx = samdb_connect(cldapd, task->event_ctx, task->lp_ctx, system_session(cldapd, task->lp_ctx)); if (cldapd->samctx == NULL) { - task_server_terminate(task, "cldapd failed to open samdb"); + task_server_terminate(task, "cldapd failed to open samdb", true); return; } /* start listening on the configured network interfaces */ status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "cldapd failed to setup interfaces"); + task_server_terminate(task, "cldapd failed to setup interfaces", true); return; } diff --git a/source4/dsdb/kcc/kcc_periodic.c b/source4/dsdb/kcc/kcc_periodic.c index 3af79d8b89..dae0c1e235 100644 --- a/source4/dsdb/kcc/kcc_periodic.c +++ b/source4/dsdb/kcc/kcc_periodic.c @@ -172,7 +172,7 @@ static void kccsrv_periodic_handler_te(struct tevent_context *ev, struct tevent_ status = kccsrv_periodic_schedule(service, service->periodic.interval); if (!W_ERROR_IS_OK(status)) { - task_server_terminate(service->task, win_errstr(status)); + task_server_terminate(service->task, win_errstr(status), true); return; } } diff --git a/source4/dsdb/kcc/kcc_service.c b/source4/dsdb/kcc/kcc_service.c index 2279879000..32e09ac989 100644 --- a/source4/dsdb/kcc/kcc_service.c +++ b/source4/dsdb/kcc/kcc_service.c @@ -151,10 +151,10 @@ static void kccsrv_task_init(struct task_server *task) switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: - task_server_terminate(task, "kccsrv: no KCC required in standalone configuration"); + task_server_terminate(task, "kccsrv: no KCC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: - task_server_terminate(task, "kccsrv: no KCC required in domain member configuration"); + task_server_terminate(task, "kccsrv: no KCC required in domain member configuration", false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want a KCC */ @@ -165,7 +165,7 @@ static void kccsrv_task_init(struct task_server *task) service = talloc_zero(task, struct kccsrv_service); if (!service) { - task_server_terminate(task, "kccsrv_task_init: out of memory"); + task_server_terminate(task, "kccsrv_task_init: out of memory", true); return; } service->task = task; @@ -174,9 +174,10 @@ static void kccsrv_task_init(struct task_server *task) status = kccsrv_init_creds(service); if (!W_ERROR_IS_OK(status)) { - task_server_terminate(task, talloc_asprintf(task, - "kccsrv: Failed to obtain server credentials: %s\n", - win_errstr(status))); + task_server_terminate(task, + talloc_asprintf(task, + "kccsrv: Failed to obtain server credentials: %s\n", + win_errstr(status)), true); return; } @@ -184,7 +185,7 @@ static void kccsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to connect to local samdb: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -192,7 +193,7 @@ static void kccsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to load partitions: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -205,7 +206,7 @@ static void kccsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to periodic schedule: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } diff --git a/source4/dsdb/repl/drepl_notify.c b/source4/dsdb/repl/drepl_notify.c index 73280917c5..d354b4e299 100644 --- a/source4/dsdb/repl/drepl_notify.c +++ b/source4/dsdb/repl/drepl_notify.c @@ -368,7 +368,7 @@ static void dreplsrv_notify_handler_te(struct tevent_context *ev, struct tevent_ status = dreplsrv_notify_schedule(service, service->notify.interval); if (!W_ERROR_IS_OK(status)) { - task_server_terminate(service->task, win_errstr(status)); + task_server_terminate(service->task, win_errstr(status), false); return; } } diff --git a/source4/dsdb/repl/drepl_periodic.c b/source4/dsdb/repl/drepl_periodic.c index 377cecbe99..61d5598207 100644 --- a/source4/dsdb/repl/drepl_periodic.c +++ b/source4/dsdb/repl/drepl_periodic.c @@ -46,7 +46,7 @@ static void dreplsrv_periodic_handler_te(struct tevent_context *ev, struct teven status = dreplsrv_periodic_schedule(service, service->periodic.interval); if (!W_ERROR_IS_OK(status)) { - task_server_terminate(service->task, win_errstr(status)); + task_server_terminate(service->task, win_errstr(status), false); return; } } diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index 75ce42b91a..34853c85f9 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -138,10 +138,12 @@ static void dreplsrv_task_init(struct task_server *task) switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: - task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration"); + task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration", + false); return; case ROLE_DOMAIN_MEMBER: - task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration"); + task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration", + false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want DSDB replication */ @@ -152,7 +154,7 @@ static void dreplsrv_task_init(struct task_server *task) service = talloc_zero(task, struct dreplsrv_service); if (!service) { - task_server_terminate(task, "dreplsrv_task_init: out of memory"); + task_server_terminate(task, "dreplsrv_task_init: out of memory", true); return; } service->task = task; @@ -163,7 +165,7 @@ static void dreplsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to obtain server credentials: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -171,7 +173,7 @@ static void dreplsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to connect to local samdb: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -179,7 +181,7 @@ static void dreplsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to load partitions: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -190,7 +192,7 @@ static void dreplsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to periodic schedule: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } @@ -200,7 +202,7 @@ static void dreplsrv_task_init(struct task_server *task) if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to setup notify schedule: %s\n", - win_errstr(status))); + win_errstr(status)), true); return; } diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index c861f7ae3e..a67aa09461 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -662,10 +662,10 @@ static void kdc_task_init(struct task_server *task) switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: - task_server_terminate(task, "kdc: no KDC required in standalone configuration"); + task_server_terminate(task, "kdc: no KDC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: - task_server_terminate(task, "kdc: no KDC required in member server configuration"); + task_server_terminate(task, "kdc: no KDC required in member server configuration", false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want a KDC */ @@ -675,7 +675,7 @@ static void kdc_task_init(struct task_server *task) load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); if (iface_count(ifaces) == 0) { - task_server_terminate(task, "kdc: no network interfaces configured"); + task_server_terminate(task, "kdc: no network interfaces configured", false); return; } @@ -683,7 +683,7 @@ static void kdc_task_init(struct task_server *task) kdc = talloc(task, struct kdc_server); if (kdc == NULL) { - task_server_terminate(task, "kdc: out of memory"); + task_server_terminate(task, "kdc: out of memory", true); return; } @@ -695,7 +695,7 @@ static void kdc_task_init(struct task_server *task) if (ret) { DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", error_message(ret))); - task_server_terminate(task, "kdc: krb5_init_context failed"); + task_server_terminate(task, "kdc: krb5_init_context failed", true); return; } @@ -704,14 +704,14 @@ static void kdc_task_init(struct task_server *task) ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, &kdc->config); if(ret) { - task_server_terminate(task, "kdc: failed to get KDC configuration"); + task_server_terminate(task, "kdc: failed to get KDC configuration", true); return; } kdc->config->logf = kdc->smb_krb5_context->logf; kdc->config->db = talloc(kdc, struct HDB *); if (!kdc->config->db) { - task_server_terminate(task, "kdc: out of memory"); + task_server_terminate(task, "kdc: out of memory", true); return; } kdc->config->num_db = 1; @@ -720,7 +720,7 @@ static void kdc_task_init(struct task_server *task) kdc->smb_krb5_context->krb5_context, &kdc->config->db[0]); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed"); + task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true); return; } @@ -728,7 +728,7 @@ static void kdc_task_init(struct task_server *task) kdc->hdb_samba4_context = talloc(kdc, struct hdb_samba4_context); if (!kdc->hdb_samba4_context) { - task_server_terminate(task, "kdc: out of memory"); + task_server_terminate(task, "kdc: out of memory", true); return; } @@ -739,13 +739,13 @@ static void kdc_task_init(struct task_server *task) PLUGIN_TYPE_DATA, "hdb", &hdb_samba4); if(ret) { - task_server_terminate(task, "kdc: failed to register hdb keytab"); + task_server_terminate(task, "kdc: failed to register hdb keytab", true); return; } ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { - task_server_terminate(task, "kdc: failed to register hdb keytab"); + task_server_terminate(task, "kdc: failed to register hdb keytab", true); return; } @@ -754,7 +754,7 @@ static void kdc_task_init(struct task_server *task) PLUGIN_TYPE_DATA, "windc", &windc_plugin_table); if(ret) { - task_server_terminate(task, "kdc: failed to register hdb keytab"); + task_server_terminate(task, "kdc: failed to register hdb keytab", true); return; } @@ -763,14 +763,14 @@ static void kdc_task_init(struct task_server *task) /* start listening on the configured network interfaces */ status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "kdc failed to setup interfaces"); + task_server_terminate(task, "kdc failed to setup interfaces", true); return; } status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, kdc_check_generic_kerberos, kdc); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "nbtd failed to setup monitoring"); + task_server_terminate(task, "nbtd failed to setup monitoring", true); return; } diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index b119620339..344015892e 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -568,10 +568,12 @@ static void ldapsrv_task_init(struct task_server *task) switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: - task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration"); + task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration", + false); return; case ROLE_DOMAIN_MEMBER: - task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration"); + task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration", + false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want an LDAP server */ @@ -642,7 +644,7 @@ static void ldapsrv_task_init(struct task_server *task) */ if (!directory_create_or_exist(priv_dir, geteuid(), 0750)) { task_server_terminate(task, "Cannot create ldap " - "privileged ldapi directory"); + "privileged ldapi directory", true); return; } ldapi_path = talloc_asprintf(ldap_service, "%s/ldapi", priv_dir); @@ -666,7 +668,7 @@ static void ldapsrv_task_init(struct task_server *task) return; failed: - task_server_terminate(task, "Failed to startup ldap server task"); + task_server_terminate(task, "Failed to startup ldap server task", true); } diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 3c518828ab..c82ad398ff 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -22,6 +22,7 @@ #ifndef IRPC_H #define IRPC_H +#include "lib/messaging/messaging.h" #include "librpc/gen_ndr/irpc.h" #include "librpc/gen_ndr/server_id.h" diff --git a/source4/lib/messaging/messaging.h b/source4/lib/messaging/messaging.h index c91a31d285..4ec69c8f34 100644 --- a/source4/lib/messaging/messaging.h +++ b/source4/lib/messaging/messaging.h @@ -36,4 +36,7 @@ struct messaging_context; /* temporary messaging endpoints are allocated above this line */ #define MSG_TMP_BASE 1000 +/* taskid for messaging of parent process */ +#define SAMBA_PARENT_TASKID 0 + #endif diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl index 41787355a9..24326e434e 100644 --- a/source4/librpc/idl/irpc.idl +++ b/source4/librpc/idl/irpc.idl @@ -141,4 +141,11 @@ import "misc.idl", "security.idl", "nbt.idl"; [out,switch_is(level)] smbsrv_info info ); + /* + called when samba should shutdown + */ + void samba_terminate( + [in] astring reason + ); + } diff --git a/source4/nbt_server/irpc.c b/source4/nbt_server/irpc.c index 951f1d296a..dbaebf66f7 100644 --- a/source4/nbt_server/irpc.c +++ b/source4/nbt_server/irpc.c @@ -180,7 +180,7 @@ void nbtd_register_irpc(struct nbtd_server *nbtsrv) status = IRPC_REGISTER(task->msg_ctx, irpc, NBTD_INFORMATION, nbtd_information, nbtsrv); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "nbtd failed to setup monitoring"); + task_server_terminate(task, "nbtd failed to setup monitoring", true); return; } @@ -188,7 +188,7 @@ void nbtd_register_irpc(struct nbtd_server *nbtsrv) nbtd_getdcname, nbtsrv); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "nbtd failed to setup getdcname " - "handler"); + "handler", true); return; } @@ -196,7 +196,7 @@ void nbtd_register_irpc(struct nbtd_server *nbtsrv) nbtd_proxy_wins_challenge, nbtsrv); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "nbtd failed to setup wins challenge " - "handler"); + "handler", true); return; } @@ -204,7 +204,7 @@ void nbtd_register_irpc(struct nbtd_server *nbtsrv) nbtd_proxy_wins_release_demand, nbtsrv); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "nbtd failed to setup wins release demand " - "handler"); + "handler", true); return; } } diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c index e6ff5003bf..4a02feb6fc 100644 --- a/source4/nbt_server/nbt_server.c +++ b/source4/nbt_server/nbt_server.c @@ -42,7 +42,7 @@ static void nbtd_task_init(struct task_server *task) load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); if (iface_count(ifaces) == 0) { - task_server_terminate(task, "nbtd: no network interfaces configured"); + task_server_terminate(task, "nbtd: no network interfaces configured", false); return; } @@ -50,7 +50,7 @@ static void nbtd_task_init(struct task_server *task) nbtsrv = talloc(task, struct nbtd_server); if (nbtsrv == NULL) { - task_server_terminate(task, "nbtd: out of memory"); + task_server_terminate(task, "nbtd: out of memory", true); return; } @@ -62,20 +62,20 @@ static void nbtd_task_init(struct task_server *task) /* start listening on the configured network interfaces */ status = nbtd_startup_interfaces(nbtsrv, task->lp_ctx, ifaces); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "nbtd failed to setup interfaces"); + task_server_terminate(task, "nbtd failed to setup interfaces", true); return; } nbtsrv->sam_ctx = samdb_connect(nbtsrv, task->event_ctx, task->lp_ctx, system_session(nbtsrv, task->lp_ctx)); if (nbtsrv->sam_ctx == NULL) { - task_server_terminate(task, "nbtd failed to open samdb"); + task_server_terminate(task, "nbtd failed to open samdb", true); return; } /* start the WINS server, if appropriate */ status = nbtd_winsserver_init(nbtsrv); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "nbtd failed to start WINS server"); + task_server_terminate(task, "nbtd failed to start WINS server", true); return; } diff --git a/source4/ntp_signd/ntp_signd.c b/source4/ntp_signd/ntp_signd.c index 8ea7fe4ff9..a9c6769821 100644 --- a/source4/ntp_signd/ntp_signd.c +++ b/source4/ntp_signd/ntp_signd.c @@ -347,7 +347,7 @@ static void ntp_signd_task_init(struct task_server *task) char *error = talloc_asprintf(task, "Cannot create NTP signd pipe directory: %s", lp_ntp_signd_socket_directory(task->lp_ctx)); task_server_terminate(task, - error); + error, true); return; } @@ -364,7 +364,7 @@ static void ntp_signd_task_init(struct task_server *task) ntp_signd = talloc(task, struct ntp_signd_server); if (ntp_signd == NULL) { - task_server_terminate(task, "ntp_signd: out of memory"); + task_server_terminate(task, "ntp_signd: out of memory", true); return; } @@ -373,7 +373,7 @@ static void ntp_signd_task_init(struct task_server *task) /* Must be system to get at the password hashes */ ntp_signd->samdb = samdb_connect(ntp_signd, task->event_ctx, task->lp_ctx, system_session(ntp_signd, task->lp_ctx)); if (ntp_signd->samdb == NULL) { - task_server_terminate(task, "ntp_signd failed to open samdb"); + task_server_terminate(task, "ntp_signd failed to open samdb", true); return; } diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c index 3d5c364ec9..1c23eb967c 100644 --- a/source4/rpc_server/service_rpc.c +++ b/source4/rpc_server/service_rpc.c @@ -714,7 +714,7 @@ static void dcesrv_task_init(struct task_server *task) return; failed: - task_server_terminate(task, "Failed to startup dcerpc server task"); + task_server_terminate(task, "Failed to startup dcerpc server task", true); } NTSTATUS server_service_rpc_init(void) diff --git a/source4/smb_server/smb_samba3.c b/source4/smb_server/smb_samba3.c index 1c84392b0c..e201cdb1e9 100644 --- a/source4/smb_server/smb_samba3.c +++ b/source4/smb_server/smb_samba3.c @@ -165,7 +165,7 @@ static void samba3_smb_task_init(struct task_server *task) return; failed: - task_server_terminate(task, "Failed to startup samba3 smb task"); + task_server_terminate(task, "Failed to startup samba3 smb task", true); } /* called at smbd startup - register ourselves as a server service */ diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 2811693800..9b10f66b2c 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -249,7 +249,7 @@ static void smbsrv_task_init(struct task_server *task) return; failed: - task_server_terminate(task, "Failed to startup smb server task"); + task_server_terminate(task, "Failed to startup smb server task", true); } /* called at smbd startup - register ourselves as a server service */ diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index 738ace95c7..ff57a0bc34 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -84,7 +84,9 @@ static void single_new_task(struct tevent_context *ev, void (*new_task)(struct tevent_context *, struct loadparm_context *, struct server_id, void *), void *private_data) { - static uint32_t taskid = 0; + /* start our taskids at 1, zero is reserved for the top + level samba task */ + static uint32_t taskid = 1; /* We use 1 so we cannot collide in with cluster ids generated * in the accept connection above, and unlikly to collide with diff --git a/source4/smbd/server.c b/source4/smbd/server.c index 73dbec0120..d150161e05 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -40,6 +40,9 @@ #include "param/param.h" #include "dsdb/samdb/samdb.h" #include "auth/session.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/ndr_irpc.h" +#include "cluster/cluster.h" /* recursively delete a directory tree @@ -192,6 +195,43 @@ static void prime_samdb_schema(struct tevent_context *event_ctx) talloc_free(samdb_context); } + +/* + called when a fatal condition occurs in a child task + */ +static NTSTATUS samba_terminate(struct irpc_message *msg, + struct samba_terminate *r) +{ + DEBUG(0,("samba_terminate: %s\n", r->in.reason)); + exit(1); +} + +/* + setup messaging for the top level samba (parent) task + */ +static NTSTATUS setup_parent_messaging(struct tevent_context *event_ctx, + struct loadparm_context *lp_ctx) +{ + struct messaging_context *msg; + NTSTATUS status; + + msg = messaging_init(talloc_autofree_context(), + lp_messaging_path(event_ctx, lp_ctx), + cluster_id(0, SAMBA_PARENT_TASKID), + lp_iconv_convenience(lp_ctx), + event_ctx); + NT_STATUS_HAVE_NO_MEMORY(msg); + + irpc_add_name(msg, "samba"); + + status = IRPC_REGISTER(msg, irpc, SAMBA_TERMINATE, + samba_terminate, NULL); + + return status; +} + + + /* main server. */ @@ -363,6 +403,12 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ prime_samdb_schema(event_ctx); + status = setup_parent_messaging(event_ctx, cmdline_lp_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status))); + return 1; + } + DEBUG(0,("%s: using '%s' process model\n", binary_name, model)); status = server_service_startup(event_ctx, cmdline_lp_ctx, model, lp_server_services(cmdline_lp_ctx)); diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c index 940edf2cb5..96d572e813 100644 --- a/source4/smbd/service_named_pipe.c +++ b/source4/smbd/service_named_pipe.c @@ -477,6 +477,8 @@ NTSTATUS stream_setup_named_pipe(struct tevent_context *event_context, if (!directory_create_or_exist(dirname, geteuid(), 0700)) { status = map_nt_error_from_unix(errno); + DEBUG(0,(__location__ ": Failed to create stream pipe directory %s - %s\n", + dirname, nt_errstr(status))); goto fail; } diff --git a/source4/smbd/service_task.c b/source4/smbd/service_task.c index c4fd3d4e98..5db8995764 100644 --- a/source4/smbd/service_task.c +++ b/source4/smbd/service_task.c @@ -25,15 +25,29 @@ #include "smbd/service_task.h" #include "lib/messaging/irpc.h" #include "param/param.h" +#include "librpc/gen_ndr/ndr_irpc.h" /* terminate a task service */ -void task_server_terminate(struct task_server *task, const char *reason) +void task_server_terminate(struct task_server *task, const char *reason, bool fatal) { struct tevent_context *event_ctx = task->event_ctx; const struct model_ops *model_ops = task->model_ops; DEBUG(0,("task_server_terminate: [%s]\n", reason)); + + if (fatal) { + struct samba_terminate r; + struct server_id *sid; + + sid = irpc_servers_byname(task->msg_ctx, task, "samba"); + + r.in.reason = reason; + IRPC_CALL(task->msg_ctx, sid[0], + irpc, SAMBA_TERMINATE, + &r, NULL); + } + model_ops->terminate(event_ctx, task->lp_ctx, reason); /* don't free this above, it might contain the 'reason' being printed */ @@ -72,7 +86,7 @@ static void task_server_callback(struct tevent_context *event_ctx, lp_iconv_convenience(task->lp_ctx), task->event_ctx); if (!task->msg_ctx) { - task_server_terminate(task, "messaging_init() failed"); + task_server_terminate(task, "messaging_init() failed", true); return; } diff --git a/source4/web_server/web_server.c b/source4/web_server/web_server.c index 2a2bfbb13b..af11def5a5 100644 --- a/source4/web_server/web_server.c +++ b/source4/web_server/web_server.c @@ -353,7 +353,7 @@ static void websrv_task_init(struct task_server *task) return; failed: - task_server_terminate(task, "websrv_task_init: failed to startup web server task"); + task_server_terminate(task, "websrv_task_init: failed to startup web server task", true); } diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c index 95be49d1e3..d3142ff52a 100644 --- a/source4/winbind/wb_server.c +++ b/source4/winbind/wb_server.c @@ -125,21 +125,21 @@ static void winbind_task_init(struct task_server *task) model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) { task_server_terminate(task, - "Can't find 'single' process model_ops"); + "Can't find 'single' process model_ops", true); return; } /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */ if (!directory_create_or_exist(lp_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755)) { task_server_terminate(task, - "Cannot create winbindd pipe directory"); + "Cannot create winbindd pipe directory", true); return; } /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */ if (!directory_create_or_exist(lp_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750)) { task_server_terminate(task, - "Cannot create winbindd privileged pipe directory"); + "Cannot create winbindd privileged pipe directory", true); return; } @@ -149,13 +149,13 @@ static void winbind_task_init(struct task_server *task) status = wbsrv_setup_domains(service); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, nt_errstr(status)); + task_server_terminate(task, nt_errstr(status), true); return; } service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx); if (service->idmap_ctx == NULL) { - task_server_terminate(task, "Failed to load idmap database"); + task_server_terminate(task, "Failed to load idmap database", true); return; } @@ -202,15 +202,15 @@ static void winbind_task_init(struct task_server *task) listen_failed: DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n", listen_socket->socket_path, nt_errstr(status))); - task_server_terminate(task, nt_errstr(status)); + task_server_terminate(task, nt_errstr(status), true); return; irpc_failed: DEBUG(0,("wbsrv_init_irpc() failed - %s\n", nt_errstr(status))); - task_server_terminate(task, nt_errstr(status)); + task_server_terminate(task, nt_errstr(status), true); return; nomem: - task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY)); + task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true); return; } diff --git a/source4/wrepl_server/wrepl_periodic.c b/source4/wrepl_server/wrepl_periodic.c index 4771544428..94391273ca 100644 --- a/source4/wrepl_server/wrepl_periodic.c +++ b/source4/wrepl_server/wrepl_periodic.c @@ -55,7 +55,7 @@ static void wreplsrv_periodic_handler_te(struct tevent_context *ev, struct teven status = wreplsrv_periodic_schedule(service, service->config.periodic_interval); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(service->task, nt_errstr(status)); + task_server_terminate(service->task, nt_errstr(status), false); return; } diff --git a/source4/wrepl_server/wrepl_server.c b/source4/wrepl_server/wrepl_server.c index c8316a5f4c..a33a3d685e 100644 --- a/source4/wrepl_server/wrepl_server.c +++ b/source4/wrepl_server/wrepl_server.c @@ -459,7 +459,7 @@ static void wreplsrv_task_init(struct task_server *task) service = talloc_zero(task, struct wreplsrv_service); if (!service) { - task_server_terminate(task, "wreplsrv_task_init: out of memory"); + task_server_terminate(task, "wreplsrv_task_init: out of memory", true); return; } service->task = task; @@ -471,7 +471,7 @@ static void wreplsrv_task_init(struct task_server *task) */ status = wreplsrv_open_winsdb(service, task->lp_ctx); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "wreplsrv_task_init: wreplsrv_open_winsdb() failed"); + task_server_terminate(task, "wreplsrv_task_init: wreplsrv_open_winsdb() failed", true); return; } @@ -480,7 +480,7 @@ static void wreplsrv_task_init(struct task_server *task) */ status = wreplsrv_setup_partners(service); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_partners() failed"); + task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_partners() failed", true); return; } @@ -490,13 +490,13 @@ static void wreplsrv_task_init(struct task_server *task) */ status = wreplsrv_setup_sockets(service, task->lp_ctx); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_sockets() failed"); + task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_sockets() failed", true); return; } status = wreplsrv_setup_periodic(service); if (!NT_STATUS_IS_OK(status)) { - task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_periodic() failed"); + task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_periodic() failed", true); return; } -- cgit