summaryrefslogtreecommitdiff
path: root/source4/lib/stream
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-11-23 00:30:58 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:46:38 -0500
commit69c531b75c2aa969fe3e028b92ea5817be574575 (patch)
treed03a352d1ff0f5cf9b27d61c9f79610754fa4793 /source4/lib/stream
parent2a311277e5df224dd07e21a96ec2e561ef4d764c (diff)
downloadsamba-69c531b75c2aa969fe3e028b92ea5817be574575.tar.gz
r11870: fixed the problem volker reported with the RPX-XPLOGIN test. The
problem was caused by a callback destroying the packet processing context while that context was being used in packet_recv() This is the first time we have used the ability of talloc destructors to 'refuse' a free request. It works well in this case as it makes the composite API simpler to use for other code, and isolates the complexity of having callbacks destroying the packet context to the packet.c code. (This used to be commit b1b2d86541a376f1ef33fae897f750005c386ebe)
Diffstat (limited to 'source4/lib/stream')
-rw-r--r--source4/lib/stream/packet.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/source4/lib/stream/packet.c b/source4/lib/stream/packet.c
index 45ca1feb45a..54cf662e2e7 100644
--- a/source4/lib/stream/packet.c
+++ b/source4/lib/stream/packet.c
@@ -47,6 +47,9 @@ struct packet_context {
BOOL recv_disable;
BOOL nofree;
+ BOOL busy;
+ BOOL destructor_called;
+
struct send_element {
struct send_element *next, *prev;
DATA_BLOB blob;
@@ -55,11 +58,34 @@ struct packet_context {
};
/*
+ a destructor used when we are processing packets to prevent freeing of this
+ context while it is being used
+*/
+static int packet_destructor(void *p)
+{
+ struct packet_context *pc = talloc_get_type(p, struct packet_context);
+
+ if (pc->busy) {
+ pc->destructor_called = True;
+ /* now we refuse the talloc_free() request. The free will
+ happen again in the packet_recv() code */
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
initialise a packet receiver
*/
struct packet_context *packet_init(TALLOC_CTX *mem_ctx)
{
- return talloc_zero(mem_ctx, struct packet_context);
+ struct packet_context *pc = talloc_zero(mem_ctx, struct packet_context);
+ if (pc != NULL) {
+ talloc_set_destructor(pc, packet_destructor);
+ }
+ return pc;
}
@@ -205,6 +231,7 @@ static void packet_next_event(struct event_context *ev, struct timed_event *te,
}
}
+
/*
call this when the socket becomes readable to kick off the whole
stream parsing process
@@ -342,8 +369,17 @@ next_partial:
pc->processing = 1;
}
+ pc->busy = True;
+
status = pc->callback(pc->private, blob);
+ pc->busy = False;
+
+ if (pc->destructor_called) {
+ talloc_free(pc);
+ return;
+ }
+
if (pc->processing) {
if (pc->processing > 1) {
EVENT_FD_READABLE(pc->fde);