summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2014-04-02 16:45:25 -0700
committerKarolin Seeger <kseeger@samba.org>2014-04-07 11:55:50 +0200
commite6ff1291fa940294689d46bd2795281d45fbc07e (patch)
tree0308d8ec43edc19e3e7b41f6fe1f57a4bc99540d
parentb649fdb8d63a5b14bb9dc567de1ddd640ae165f3 (diff)
downloadsamba-e6ff1291fa940294689d46bd2795281d45fbc07e.tar.gz
s3: messages: Implement cleanup of dead records.
When a smbd process dies, pending messages.tdb records for this process might not get cleaned up. Implement a cleanup for dead records that is triggered after a smbd dies uncleanly; the records for that PID are deleted. Based on a patchset from Christof Schmitt <cs@samba.org>. Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Christof Schmitt <cs@samba.org> (cherry picked from commit 837671f47670b16726aa96ba7a0902974a1037eb) Bug: https://bugzilla.samba.org/show_bug.cgi?id=10534 Cleanup messages.tdb record after unclean smbd shutdown Autobuild-User(v4-0-test): Karolin Seeger <kseeger@samba.org> Autobuild-Date(v4-0-test): Mon Apr 7 11:55:50 CEST 2014 on sn-devel-104
-rw-r--r--source3/include/messages.h6
-rw-r--r--source3/lib/messages.c17
-rw-r--r--source3/lib/messages_local.c38
-rw-r--r--source3/smbd/server.c7
4 files changed, 68 insertions, 0 deletions
diff --git a/source3/include/messages.h b/source3/include/messages.h
index 4b45901afda..a45f5a5d028 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -101,6 +101,9 @@ bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx);
void *messaging_tdb_event(TALLOC_CTX *mem_ctx, struct messaging_context *msg,
struct tevent_context *ev);
+NTSTATUS messaging_tdb_cleanup(struct messaging_context *msg_ctx,
+ struct server_id pid);
+
NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx,
TALLOC_CTX *mem_ctx,
struct messaging_backend **presult);
@@ -140,6 +143,9 @@ NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
void messaging_dispatch_rec(struct messaging_context *msg_ctx,
struct messaging_rec *rec);
+void messaging_cleanup_server(struct messaging_context *msg_ctx,
+ struct server_id pid);
+
#include "librpc/gen_ndr/ndr_messaging.h"
#endif
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index cd763e7265a..5e738c74619 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -397,4 +397,21 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx,
return;
}
+/*
+ Call when a process has terminated abnormally.
+*/
+void messaging_cleanup_server(struct messaging_context *msg_ctx,
+ struct server_id server)
+{
+ if (server_id_is_disconnected(&server)) {
+ return;
+ }
+
+ if (!procid_is_local(&server)) {
+ return;
+ }
+
+ (void)messaging_tdb_cleanup(msg_ctx, server);
+
+}
/** @} **/
diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index 6b63d729254..859eeb858e3 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -45,6 +45,7 @@
#include "includes.h"
#include "system/filesys.h"
#include "messages.h"
+#include "serverid.h"
#include "lib/tdb_wrap/tdb_wrap.h"
#include "lib/param/param.h"
@@ -200,6 +201,43 @@ static TDB_DATA message_key_pid(TALLOC_CTX *mem_ctx, struct server_id pid)
return kbuf;
}
+/*******************************************************************
+ Called when a process has terminated abnormally. Remove all messages
+ pending for it.
+******************************************************************/
+
+NTSTATUS messaging_tdb_cleanup(struct messaging_context *msg_ctx,
+ struct server_id pid)
+{
+ struct messaging_tdb_context *ctx = talloc_get_type(
+ msg_ctx->local->private_data,
+ struct messaging_tdb_context);
+ struct tdb_wrap *tdb = ctx->tdb;
+ TDB_DATA key;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ key = message_key_pid(frame, pid);
+ /*
+ * We have to lock the key to avoid
+ * races in case the server_id was
+ * re-used and is active (a remote
+ * possibility, true). We only
+ * clean up the database if we
+ * know server_id doesn't exist
+ * while checked under the chainlock.
+ */
+ if (tdb_chainlock(tdb->tdb, key) != 0) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_LOCK_NOT_GRANTED;
+ }
+ if (!serverid_exists(&pid)) {
+ (void)tdb_delete(tdb->tdb, key);
+ }
+ tdb_chainunlock(tdb->tdb, key);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
/*
Fetch the messaging array for a process
*/
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index a86fa488c80..86c20baf435 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -455,6 +455,13 @@ static void remove_child_pid(struct smbd_parent_context *parent,
parent);
DEBUG(1,("Scheduled cleanup of brl and lock database after unclean shutdown\n"));
}
+
+ /*
+ * Ensure we flush any stored messages
+ * queued for the child process that
+ * terminated uncleanly.
+ */
+ messaging_cleanup_server(parent->msg_ctx, child_id);
}
if (!serverid_deregister(child_id)) {