mirror of
https://github.com/reactos/reactos.git
synced 2025-06-04 17:00:31 +00:00
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. svn path=/trunk/; revision=20149
This commit is contained in:
parent
bc49f0f151
commit
9f345c304d
7 changed files with 134 additions and 119 deletions
|
@ -647,4 +647,34 @@ NTSTATUS TCPGetPeerAddress
|
|||
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 */
|
||||
|
|
|
@ -51,11 +51,6 @@ BOOLEAN ProtocolRegistered = FALSE;
|
|||
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 ProtocolSendComplete(
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ VOID STDCALL LanReceiveWorker( PVOID Context ) {
|
|||
|
||||
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 @@ VOID LanSubmitReceiveWork(
|
|||
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 @@ NDIS_STATUS STDCALL ProtocolReceive(
|
|||
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 @@ NDIS_STATUS STDCALL ProtocolReceive(
|
|||
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 @@ NDIS_STATUS STDCALL ProtocolReceive(
|
|||
BytesTransferred = 0;
|
||||
}
|
||||
}
|
||||
TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
|
||||
TI_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
|
||||
|
||||
if (NdisStatus != NDIS_STATUS_PENDING)
|
||||
|
@ -1369,10 +1332,8 @@ VOID LANUnregisterProtocol(
|
|||
}
|
||||
|
||||
VOID LANStartup() {
|
||||
InitializeListHead( &LanWorkList );
|
||||
InitializeListHead( &LanSendCompleteList );
|
||||
KeInitializeSpinLock( &LanSendCompleteLock );
|
||||
ExInitializeWorkItem( &LanWorkItem, LanReceiveWorker, NULL );
|
||||
}
|
||||
|
||||
VOID LANShutdown() {
|
||||
|
@ -1380,15 +1341,6 @@ VOID LANShutdown() {
|
|||
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 );
|
||||
|
|
|
@ -36,4 +36,4 @@
|
|||
#include <ports.h>
|
||||
#include <ipifcons.h>
|
||||
#include <ndk/ntndk.h>
|
||||
|
||||
#include <chew/chew.h>
|
||||
|
|
|
@ -176,4 +176,6 @@ NTSTATUS TCPStartup(
|
|||
NTSTATUS TCPShutdown(
|
||||
VOID);
|
||||
|
||||
VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
|
||||
|
||||
#endif /* __TCP_H */
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -135,6 +135,30 @@ VOID DispDataRequestComplete(
|
|||
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,
|
||||
|
@ -150,6 +174,8 @@ VOID DDKAPI DispCancelRequest(
|
|||
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 @@ VOID DDKAPI DispCancelRequest(
|
|||
|
||||
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 @@ VOID DDKAPI DispCancelRequest(
|
|||
/* Try canceling the request */
|
||||
switch(MinorFunction) {
|
||||
case TDI_SEND:
|
||||
TCPDisconnect
|
||||
( TranContext->Handle.ConnectionContext,
|
||||
TDI_DISCONNECT_RELEASE,
|
||||
NULL,
|
||||
NULL,
|
||||
DispDataRequestComplete,
|
||||
Irp );
|
||||
break;
|
||||
|
||||
case TDI_RECEIVE:
|
||||
TCPDisconnect
|
||||
( TranContext->Handle.ConnectionContext,
|
||||
TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE,
|
||||
NULL,
|
||||
NULL,
|
||||
DispDataRequestComplete,
|
||||
Irp );
|
||||
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 );
|
||||
|
||||
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 @@ VOID DDKAPI DispCancelRequest(
|
|||
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,9 +236,10 @@ VOID DDKAPI DispCancelRequest(
|
|||
break;
|
||||
}
|
||||
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||
if( Irp->IoStatus.Status == STATUS_PENDING )
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
DispCancelComplete(FileObject);
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
||||
}
|
||||
|
|
|
@ -619,6 +619,8 @@ VOID STDCALL TiUnload(
|
|||
}
|
||||
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
|
||||
#endif
|
||||
ChewShutdown();
|
||||
|
||||
/* Cancel timer */
|
||||
KeCancelTimer(&IPTimer);
|
||||
|
||||
|
@ -734,6 +736,8 @@ DriverEntry(
|
|||
return Status;
|
||||
}
|
||||
|
||||
ChewInit( IPDeviceObject );
|
||||
|
||||
/* Create RawIP device object */
|
||||
Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
|
||||
FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
|
||||
|
|
Loading…
Reference in a new issue