From f91054d29f4d6633d3a0f3dc4e9f9546f1f9509e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Apr 2014 16:45:25 -0700 Subject: [PATCH] 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 . Signed-off-by: Jeremy Allison Reviewed-by: Christof Schmitt (cherry picked from commit 837671f47670b16726aa96ba7a0902974a1037eb) --- source3/include/messages.h | 6 ++++++ source3/lib/messages.c | 17 +++++++++++++++++ source3/lib/messages_local.c | 38 ++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 7 +++++++ 4 files changed, 68 insertions(+), 0 deletions(-) diff --git a/source3/include/messages.h b/source3/include/messages.h index 4b45901..a45f5a5 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 cd763e7..5e738c7 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 6b63d72..859eeb8 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 a86fa48..86c20ba 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)) { -- 1.7.1