Patch to fix bugcheck at exit for various TCP wielding apps. This puts in a work item for socket shutdown that decouples the IRP cancel from the actual (PASSIVE_LEVEL) tcp accounting chores.
Uses the CHEW static lib that I put in to gather workitem code into one nice sane happy place.
It seems like doing the same to loopback.c is detrimental and I suspect that it's due to nasty reentrancy issues in our code. I'll likely adapt chew lib so we can use it there too. Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c Modified: trunk/reactos/drivers/net/tcpip/datalink/lan.c Modified: trunk/reactos/drivers/net/tcpip/include/precomp.h Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c Modified: trunk/reactos/drivers/net/tcpip/tcpip.xml _____
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c --- trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c 2005-12-13 20:17:25 UTC (rev 20149) @@ -647,4 +647,34 @@
return STATUS_SUCCESS; }
+VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) { + PLIST_ENTRY Entry; + PLIST_ENTRY ListHead[4]; + KIRQL OldIrql; + PTDI_BUCKET Bucket; + UINT i = 0; + + ListHead[0] = &Endpoint->ReceiveRequest; + ListHead[1] = &Endpoint->ConnectRequest; + ListHead[2] = &Endpoint->ListenRequest; + ListHead[3] = 0; + + TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql ); + + for( i = 0; ListHead[i]; i++ ) { + for( Entry = ListHead[i]->Flink; + Entry != ListHead[i]; + Entry = Entry->Flink ) { + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); + + if( Bucket->Request.RequestContext == Irp ) { + RemoveEntryList( &Bucket->Entry ); + break; + } + } + } + + TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql ); +} + /* EOF */ _____
Modified: trunk/reactos/drivers/net/tcpip/datalink/lan.c --- trunk/reactos/drivers/net/tcpip/datalink/lan.c 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/datalink/lan.c 2005-12-13 20:17:25 UTC (rev 20149) @@ -51,11 +51,6 @@
LIST_ENTRY AdapterListHead; KSPIN_LOCK AdapterListLock;
-/* Work around being called back into afd at Dpc level */ -KSPIN_LOCK LanWorkLock; -LIST_ENTRY LanWorkList; -WORK_QUEUE_ITEM LanWorkItem; - /* Double complete protection */ KSPIN_LOCK LanSendCompleteLock; LIST_ENTRY LanSendCompleteList; @@ -289,10 +284,9 @@ } }
-VOID STDCALL LanReceiveWorker( PVOID Context ) { +VOID LanReceiveWorker( PVOID Context ) { UINT PacketType; - PLIST_ENTRY ListEntry; - PLAN_WQ_ITEM WorkItem; + PLAN_WQ_ITEM WorkItem = (PLAN_WQ_ITEM)Context; PNDIS_PACKET Packet; PLAN_ADAPTER Adapter; UINT BytesTransferred; @@ -301,60 +295,49 @@
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
- while( (ListEntry = - ExInterlockedRemoveHeadList( &LanWorkList, &LanWorkLock )) ) { - WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry); - - TI_DbgPrint(DEBUG_DATALINK, ("WorkItem: %x\n", WorkItem)); - - Packet = WorkItem->Packet; - Adapter = WorkItem->Adapter; - BytesTransferred = WorkItem->BytesTransferred; - - ExFreePool( WorkItem ); - - IPPacket.NdisPacket = Packet; - - NdisGetFirstBufferFromPacket(Packet, - &NdisBuffer, - &IPPacket.Header, - &IPPacket.ContigSize, - &IPPacket.TotalSize); - - IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred; - /* Determine which upper layer protocol that should receive - this packet and pass it to the correct receive handler */ - - TI_DbgPrint(MID_TRACE, - ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n", - IPPacket.ContigSize, IPPacket.TotalSize, - BytesTransferred)); - - PacketType = PC(IPPacket.NdisPacket)->PacketType; - IPPacket.Position = 0; - - TI_DbgPrint - (DEBUG_DATALINK, - ("Ether Type = %x ContigSize = %d Total = %d\n", - PacketType, IPPacket.ContigSize, IPPacket.TotalSize)); - - switch (PacketType) { - case ETYPE_IPv4: - case ETYPE_IPv6: - TI_DbgPrint(MID_TRACE,("Received IP Packet\n")); - IPReceive(Adapter->Context, &IPPacket); - break; - case ETYPE_ARP: - TI_DbgPrint(MID_TRACE,("Received ARP Packet\n")); - ARPReceive(Adapter->Context, &IPPacket); - default: - break; - } - - FreeNdisPacket( Packet ); + Packet = WorkItem->Packet; + Adapter = WorkItem->Adapter; + BytesTransferred = WorkItem->BytesTransferred; + + IPPacket.NdisPacket = Packet; + + NdisGetFirstBufferFromPacket(Packet, + &NdisBuffer, + &IPPacket.Header, + &IPPacket.ContigSize, + &IPPacket.TotalSize); + + IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred; + /* Determine which upper layer protocol that should receive + this packet and pass it to the correct receive handler */ + + TI_DbgPrint(MID_TRACE, + ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n", + IPPacket.ContigSize, IPPacket.TotalSize, + BytesTransferred)); + + PacketType = PC(IPPacket.NdisPacket)->PacketType; + IPPacket.Position = 0; + + TI_DbgPrint + (DEBUG_DATALINK, + ("Ether Type = %x ContigSize = %d Total = %d\n", + PacketType, IPPacket.ContigSize, IPPacket.TotalSize)); + + switch (PacketType) { + case ETYPE_IPv4: + case ETYPE_IPv6: + TI_DbgPrint(MID_TRACE,("Received IP Packet\n")); + IPReceive(Adapter->Context, &IPPacket); + break; + case ETYPE_ARP: + TI_DbgPrint(MID_TRACE,("Received ARP Packet\n")); + ARPReceive(Adapter->Context, &IPPacket); + default: + break; } - TI_DbgPrint(DEBUG_DATALINK, ("Leaving\n")); - LanReceiveWorkerBusy = FALSE; + + FreeNdisPacket( Packet ); }
VOID LanSubmitReceiveWork( @@ -362,34 +345,19 @@ PNDIS_PACKET Packet, NDIS_STATUS Status, UINT BytesTransferred) { - PLAN_WQ_ITEM WQItem; + LAN_WQ_ITEM WQItem; PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; - KIRQL OldIrql; + PVOID LanWorkItem;
TI_DbgPrint(DEBUG_DATALINK,("called\n"));
- TcpipAcquireSpinLock( &LanWorkLock, &OldIrql ); + WQItem.Packet = Packet; + WQItem.Adapter = Adapter; + WQItem.BytesTransferred = BytesTransferred;
- WQItem = ExAllocatePool( NonPagedPool, sizeof(LAN_WQ_ITEM) ); - if( !WQItem ) { - TcpipReleaseSpinLock( &LanWorkLock, OldIrql ); - return; - } - - WQItem->Packet = Packet; - WQItem->Adapter = Adapter; - WQItem->BytesTransferred = BytesTransferred; - InsertTailList( &LanWorkList, &WQItem->ListEntry ); - if( !LanReceiveWorkerBusy ) { - LanReceiveWorkerBusy = TRUE; - ExQueueWorkItem( &LanWorkItem, CriticalWorkQueue ); - TI_DbgPrint(DEBUG_DATALINK, - ("Work item inserted %x %x\n", &LanWorkItem, WQItem)); - } else { - TI_DbgPrint(DEBUG_DATALINK, - ("LAN WORKER BUSY %x %x\n", &LanWorkItem, WQItem)); - } - TcpipReleaseSpinLock( &LanWorkLock, OldIrql ); + if( !ChewCreate + ( &LanWorkItem, sizeof(LAN_WQ_ITEM), LanReceiveWorker, &WQItem ) ) + ASSERT(0); }
VOID STDCALL ProtocolTransferDataComplete( @@ -452,7 +420,6 @@ PNDIS_PACKET NdisPacket; PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; PETH_HEADER EHeader = (PETH_HEADER)HeaderBuffer; - KIRQL OldIrql;
TI_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize));
@@ -490,12 +457,9 @@ TI_DbgPrint(DEBUG_DATALINK, ("Adapter: %x (MTU %d)\n", Adapter, Adapter->MTU));
- TcpipAcquireSpinLock( &LanWorkLock, &OldIrql ); - NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, PacketSize + HeaderBufferSize ); if( NdisStatus != NDIS_STATUS_SUCCESS ) { - TcpipReleaseSpinLock( &LanWorkLock, OldIrql ); return NDIS_STATUS_NOT_ACCEPTED; }
@@ -534,7 +498,6 @@ BytesTransferred = 0; } } - TcpipReleaseSpinLock( &LanWorkLock, OldIrql ); TI_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
if (NdisStatus != NDIS_STATUS_PENDING) @@ -1369,10 +1332,8 @@ }
VOID LANStartup() { - InitializeListHead( &LanWorkList ); InitializeListHead( &LanSendCompleteList ); KeInitializeSpinLock( &LanSendCompleteLock ); - ExInitializeWorkItem( &LanWorkItem, LanReceiveWorker, NULL ); }
VOID LANShutdown() { @@ -1380,15 +1341,6 @@ PLAN_WQ_ITEM WorkItem; PLIST_ENTRY ListEntry;
- TcpipAcquireSpinLock( &LanWorkLock, &OldIrql ); - while( !IsListEmpty( &LanWorkList ) ) { - ListEntry = RemoveHeadList( &LanWorkList ); - WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry); - FreeNdisPacket( WorkItem->Packet ); - ExFreePool( WorkItem ); - } - TcpipReleaseSpinLock( &LanWorkLock, OldIrql ); - KeAcquireSpinLock( &LanSendCompleteLock, &OldIrql ); while( !IsListEmpty( &LanSendCompleteList ) ) { ListEntry = RemoveHeadList( &LanSendCompleteList ); _____
Modified: trunk/reactos/drivers/net/tcpip/include/precomp.h --- trunk/reactos/drivers/net/tcpip/include/precomp.h 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/include/precomp.h 2005-12-13 20:17:25 UTC (rev 20149) @@ -36,4 +36,4 @@
#include <ports.h> #include <ipifcons.h> #include <ndk/ntndk.h> - +#include <chew/chew.h> _____
Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h --- trunk/reactos/drivers/net/tcpip/include/tcp.h 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/include/tcp.h 2005-12-13 20:17:25 UTC (rev 20149) @@ -176,4 +176,6 @@
NTSTATUS TCPShutdown( VOID);
+VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp ); + #endif /* __TCP_H */ _____
Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c --- trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c 2005-12-13 20:17:25 UTC (rev 20149) @@ -135,7 +135,31 @@
TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n")); }
+typedef struct _DISCONNECT_TYPE { + UINT Type; + PVOID Context; + PIRP Irp; + PFILE_OBJECT FileObject; +} DISCONNECT_TYPE, *PDISCONNECT_TYPE;
+VOID DispDoDisconnect( PVOID Data ) { + PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data; + + TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n")); + TCPDisconnect + ( DisType->Context, + DisType->Type, + NULL, + NULL, + DispDataRequestComplete, + DisType->Irp ); + TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n")); + + DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0); + + DispCancelComplete(DisType->FileObject); +} + VOID DDKAPI DispCancelRequest( PDEVICE_OBJECT Device, PIRP Irp) @@ -150,6 +174,8 @@ PTRANSPORT_CONTEXT TranContext; PFILE_OBJECT FileObject; UCHAR MinorFunction; + DISCONNECT_TYPE DisType; + PVOID WorkItem; /*NTSTATUS Status = STATUS_SUCCESS;*/
TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -161,6 +187,8 @@
TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
+ Irp->IoStatus.Status = STATUS_PENDING; + #ifdef DBG if (!Irp->Cancel) TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); @@ -169,26 +197,22 @@ /* Try canceling the request */ switch(MinorFunction) { case TDI_SEND: - TCPDisconnect - ( TranContext->Handle.ConnectionContext, - TDI_DISCONNECT_RELEASE, - NULL, - NULL, - DispDataRequestComplete, - Irp ); - break; + case TDI_RECEIVE: + DisType.Type = TDI_DISCONNECT_RELEASE | + ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0); + DisType.Context = TranContext->Handle.ConnectionContext; + DisType.Irp = Irp; + DisType.FileObject = FileObject; + + TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
- case TDI_RECEIVE: - TCPDisconnect - ( TranContext->Handle.ConnectionContext, - TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE, - NULL, - NULL, - DispDataRequestComplete, - Irp ); + if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE), + DispDoDisconnect, &DisType ) ) + ASSERT(0); break;
case TDI_SEND_DATAGRAM: + Irp->IoStatus.Status = STATUS_CANCELLED; if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n")); break; @@ -198,6 +222,7 @@ break;
case TDI_RECEIVE_DATAGRAM: + Irp->IoStatus.Status = STATUS_CANCELLED; if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n")); break; @@ -211,10 +236,11 @@ break; }
+ if( Irp->IoStatus.Status == STATUS_PENDING ) + IoMarkIrpPending(Irp); + IoReleaseCancelSpinLock(Irp->CancelIrql);
- DispCancelComplete(FileObject); - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); }
_____
Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c --- trunk/reactos/drivers/net/tcpip/tcpip/main.c 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/tcpip/main.c 2005-12-13 20:17:25 UTC (rev 20149) @@ -619,6 +619,8 @@
} TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); #endif + ChewShutdown(); + /* Cancel timer */ KeCancelTimer(&IPTimer);
@@ -734,6 +736,8 @@ return Status; }
+ ChewInit( IPDeviceObject ); + /* Create RawIP device object */ Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName, FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject); _____
Modified: trunk/reactos/drivers/net/tcpip/tcpip.xml --- trunk/reactos/drivers/net/tcpip/tcpip.xml 2005-12-13 20:16:50 UTC (rev 20148) +++ trunk/reactos/drivers/net/tcpip/tcpip.xml 2005-12-13 20:17:25 UTC (rev 20149) @@ -9,6 +9,7 @@
<library>oskittcp</library> <library>ndis</library> <library>pseh</library> + <library>chew</library> <library>ntoskrnl</library> <library>hal</library> <directory name="include">