Doron,
Basically, the situation stood as following:
I had an unloadable LWF that was quueing workitems upon sends and receives of data.
IoAllocateWorkItem() was using DEVICE_OBJECT that was created by NdisRegisterDeviceEx(),
and IoQueueWorkItemEx() was called in context of FilterSendNetBufferLists() and FilterReceiveNetBufferLists() routines.
Under the normal circumstances, it all worked fine - I could unload my driver without a problem. However, when I was doing it during large upload/download (i.e. when the flow of incoming and outgoing packets was really heavy), I was crashing…
At this point I had 2 suggestions:
-
My FilterSendNetBufferListsComplete() or FilterReturnNetBufferLists() was being invoked after a driver has been already unloaded.
-
My workitem routine was being invoked after a driver has been already unloaded.
Therefore, I commented lines that call IoQueueWorkItemEx(), and introduced reference counting on packets and “IsUnloading” flag to the filter extension (I took advantage on the fact that driver cannot get unloaded until filter enters the paused state) . I hope it is needless to say that all access to the refcount and IsUnloading flag was guarded by a spinlock.
Unless “IsUnloading” flag was set, my FilterSendNetBufferLists() and FilterReceiveNetBufferLists() were incrementing the total count before sending or indicating packets (in the latter case, only if NDIS_STATUS_RESOURCES was not set), and FilterSendNetBufferListsComplete() and FilterReturnNetBufferLists() were decremeting it. FilterPause() was checking the count - if it was non-zero, it was setting “IsUnloading” flag on, and returned NDIS_STATUS_PENDING. If “IsUnloading” flag was set, my FilterSendNetBufferLists() and FilterReceiveNetBufferLists() did not proceed with sending or indicating packets, and checked the total count. If was zero, they were calling NdisFPauseComplete() before returning, and, at this point, my filter was entering the paused state.
At this point everything started working perfectly well - I could unload a driver without a problem, no matter how busy the network traffic was. However, when I uncommented the lines that queued a workitem, again, I was crashing.
Therefore, I extended the same counting logic to dealing with workitem - I incremented it before
queueing a workitem, and workitem routine decremented it, plus made sure that NdisFPauseComplete() may get called if and only if refcount for workitems is zero.
At this point,again, everything started working perfectly well - I could unload a driver without a problem, no matter how busy the network traffic was.
Anton Bassov