- Fix a race condition that occurs when an IRP gets cancelled after it is inserted into the completion queue but before it is completed

svn path=/trunk/; revision=44267
This commit is contained in:
Cameron Gutman 2009-11-22 02:32:47 +00:00
parent 83bc88465f
commit e016a230af
6 changed files with 33 additions and 20 deletions

View file

@ -21,7 +21,7 @@ NTSTATUS DGReceiveDatagram(
PVOID Context,
PIRP Irp);
VOID DGRemoveIRP(
BOOLEAN DGRemoveIRP(
PADDRESS_FILE AddrFile,
PIRP Irp);

View file

@ -96,8 +96,8 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection,
PTDI_REQUEST_KERNEL Request );
NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog );
VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection );
BOOLEAN TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection );
NTSTATUS TCPAccept
( PTDI_REQUEST Request,
PCONNECTION_ENDPOINT Listener,
@ -179,6 +179,6 @@ NTSTATUS TCPStartup(
NTSTATUS TCPShutdown(
VOID);
VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
#endif /* __TCP_H */

View file

@ -133,6 +133,7 @@ VOID NTAPI DispCancelRequest(
PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject;
UCHAR MinorFunction;
BOOLEAN DequeuedIrp = TRUE;
IoReleaseCancelSpinLock(Irp->CancelIrql);
@ -157,7 +158,7 @@ VOID NTAPI DispCancelRequest(
switch(MinorFunction) {
case TDI_SEND:
case TDI_RECEIVE:
TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
DequeuedIrp = TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
break;
case TDI_SEND_DATAGRAM:
@ -166,7 +167,7 @@ VOID NTAPI DispCancelRequest(
break;
}
DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
break;
case TDI_RECEIVE_DATAGRAM:
@ -175,19 +176,21 @@ VOID NTAPI DispCancelRequest(
break;
}
DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
break;
case TDI_CONNECT:
TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
break;
default:
TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
ASSERT(FALSE);
break;
}
IRPFinish(Irp, STATUS_CANCELLED);
if (DequeuedIrp)
IRPFinish(Irp, STATUS_CANCELLED);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
@ -207,7 +210,6 @@ VOID NTAPI DispCancelListenRequest(
PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject;
PCONNECTION_ENDPOINT Connection;
/*NTSTATUS Status = STATUS_SUCCESS;*/
IoReleaseCancelSpinLock(Irp->CancelIrql);
@ -228,13 +230,12 @@ VOID NTAPI DispCancelListenRequest(
/* Try canceling the request */
Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
TCPRemoveIRP(Connection, Irp);
TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection);
Irp->IoStatus.Information = 0;
IRPFinish(Irp, STATUS_CANCELLED);
if (TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection))
{
Irp->IoStatus.Information = 0;
IRPFinish(Irp, STATUS_CANCELLED);
}
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}

View file

@ -10,13 +10,14 @@
#include "precomp.h"
VOID DGRemoveIRP(
BOOLEAN DGRemoveIRP(
PADDRESS_FILE AddrFile,
PIRP Irp)
{
PLIST_ENTRY ListEntry;
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
KIRQL OldIrql;
BOOLEAN Found = FALSE;
TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
Irp, AddrFile));
@ -36,6 +37,7 @@ VOID DGRemoveIRP(
{
RemoveEntryList(&ReceiveRequest->ListEntry);
ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
Found = TRUE;
break;
}
}
@ -43,6 +45,8 @@ VOID DGRemoveIRP(
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Done.\n"));
return Found;
}
VOID DGDeliverData(

View file

@ -104,11 +104,12 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
return Status;
}
VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
BOOLEAN TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection ) {
PLIST_ENTRY ListEntry;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
BOOLEAN Found = FALSE;
KeAcquireSpinLock(&Listener->Lock, &OldIrql);
@ -119,6 +120,7 @@ VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
if( Bucket->AssociatedEndpoint == Connection ) {
RemoveEntryList( &Bucket->Entry );
ExFreePoolWithTag( Bucket, TDI_BUCKET_TAG );
Found = TRUE;
break;
}
@ -126,6 +128,8 @@ VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
}
KeReleaseSpinLock(&Listener->Lock, OldIrql);
return Found;
}
NTSTATUS TCPAccept ( PTDI_REQUEST Request,

View file

@ -904,12 +904,13 @@ NTSTATUS TCPGetSockAddress
return Status;
}
VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
PLIST_ENTRY Entry;
PLIST_ENTRY ListHead[4];
KIRQL OldIrql;
PTDI_BUCKET Bucket;
UINT i = 0;
BOOLEAN Found = FALSE;
ListHead[0] = &Endpoint->SendRequest;
ListHead[1] = &Endpoint->ReceiveRequest;
@ -929,12 +930,15 @@ VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
{
RemoveEntryList( &Bucket->Entry );
ExFreePoolWithTag( Bucket, TDI_BUCKET_TAG );
Found = TRUE;
break;
}
}
}
TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql );
return Found;
}
/* EOF */