Author: cgutman Date: Fri Jun 17 12:04:20 2011 New Revision: 52307
URL: http://svn.reactos.org/svn/reactos?rev=52307&view=rev Log: [IP] - Call the completion handler asynchronously to avoid a deadlock if AFD issues a synchronous request in its completion function - Complete all pending requests before closing the socket - Fixes send and receive on accepted sockets
Modified: branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/event.c branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/tcp.c
Modified: branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/event.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/TcpIpDriver/lib/driver... ============================================================================== --- branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] (original) +++ branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] Fri Jun 17 12:04:20 2011 @@ -30,10 +30,41 @@ "TIME_WAIT" };
+static +VOID +BucketCompletionWorker(PVOID Context) +{ + PTDI_BUCKET Bucket = Context; + PTCP_COMPLETION_ROUTINE Complete; + + Complete = Bucket->Request.RequestNotifyObject; + + Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); + + ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + + DereferenceObject(Bucket->AssociatedEndpoint); +} + +static +VOID +CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, BOOLEAN Synchronous) +{ + ReferenceObject(Connection); + Bucket->AssociatedEndpoint = Connection; + if (Synchronous) + { + BucketCompletionWorker(Bucket); + } + else + { + ChewCreate(BucketCompletionWorker, Bucket); + } +} + VOID FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status) { - PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
@@ -52,11 +83,7 @@ Bucket->Status = Status; Bucket->Information = 0;
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, TRUE); }
if (Status == STATUS_SUCCESS) @@ -69,11 +96,7 @@ Bucket->Status = Status; Bucket->Information = 0;
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, TRUE); }
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock))) @@ -87,11 +110,7 @@ Bucket->Status = Status; Bucket->Information = 0;
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, TRUE); }
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock))) @@ -101,11 +120,7 @@ Bucket->Status = Status; Bucket->Information = 0;
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, TRUE); }
DereferenceObject(Connection); @@ -126,7 +141,6 @@ TCPAcceptEventHandler(void *arg, struct tcp_pcb *newpcb) { PCONNECTION_ENDPOINT Connection = arg; - PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry; PIRP Irp; @@ -160,8 +174,6 @@ Bucket->AssociatedEndpoint->SocketContext);
DbgPrint("[IP, TCPAcceptEventHandler] Completing accept event %x\n", Status); - - Complete = Bucket->Request.RequestNotifyObject;
if (Status == STATUS_SUCCESS) { @@ -183,10 +195,7 @@
DbgPrint("[IP, TCPAcceptEventHandler] Done!\n");
- Complete(Bucket->Request.RequestContext, - Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, FALSE); }
DereferenceObject(Connection); @@ -196,7 +205,6 @@ TCPSendEventHandler(void *arg, u16_t space) { PCONNECTION_ENDPOINT Connection = arg; - PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry; PIRP Irp; @@ -255,11 +263,7 @@
DbgPrint("Completing send req %x\n", Status);
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, FALSE); } }
@@ -272,7 +276,6 @@ TCPRecvEventHandler(void *arg, struct pbuf *p) { PCONNECTION_ENDPOINT Connection = arg; - PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry; PIRP Irp; @@ -324,11 +327,7 @@ Bucket->Status = STATUS_SUCCESS; Bucket->Information = Received;
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, FALSE); }
DereferenceObject(Connection); @@ -342,7 +341,6 @@ TCPConnectEventHandler(void *arg, err_t err) { PCONNECTION_ENDPOINT Connection = arg; - PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
@@ -360,11 +358,7 @@
DbgPrint("[IP, TCPConnectEventHandler] Completing connection request! (0x%x)\n", err);
- Complete = Bucket->Request.RequestNotifyObject; - - Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - - ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG); + CompleteBucket(Connection, Bucket, FALSE); }
DbgPrint("[IP, TCPConnectEventHandler] Done\n");
Modified: branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/TcpIpDriver/lib/driver... ============================================================================== --- branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ branches/GSoC_2011/TcpIpDriver/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Fri Jun 17 12:04:20 2011 @@ -349,9 +349,9 @@ /* Don't try to close again if the other side closed us already */ if (Socket) { + FlushAllQueues(Connection, STATUS_CANCELLED); + LibTCPClose(Socket); - - FlushAllQueues(Connection, STATUS_CANCELLED); }
UnlockObject(Connection, OldIrql);