Hello, dear OSR administrators and users. I have a few questions about canceling IRPs.
My NDIS filter driver receives IRPs from the user in its dispatcher routine (up to 16 IRPs), marks them as pending, and when the FilterSendNetBufferLists callback is called, I take the oldest pending IRP, fill it with data from the network buffer, and complete processing of this IRP in the same routine (FilterrSendNetBufferLists).
But sometimes (very rarely), the system crashes. WinDbg shows that the current pending IRP I want to fill is invalid (MmGetSystemAddressForMdlSafe encounters address 0). I think that when something happens in my user program (sometimes FTDI returns a timeout), the user program is restarted, and the threads that issued the IRP are terminated and recreated. It's possible (I think) that pending IRPs are destroyed during this time, because the documentation states that when the user thread terminates, all IRPs ussued by that thread are canceled. And when the FilterSendNetBufferLists function tries to work with already destroyed IRPs, it crashes. What do you think?
Is the process restarting itself, by redoing its initializations? Or do you create a new process? The driver file handle cannot be closed (and hence the process cannot exit) while there are pending IRPs, and the IRPs cannot be destroyed while your driver holds them. Are you checking for cancellation when you âpopâthe oldest IRP from your list? What METHOD_XXX are you using for your IRPs?
Hello mr. Tim_Roberts.My user program(process) creates some threads for receive path and some threads for send path. All threads working autonome, only by synchronizing access to the ftdi usb device. When something happens with FTDI (for example timeout), I terminate all threads(with exitthread() or returning from first function of thread ). After I send message to driver to be be reseting. Under that message dispatch function of driver cancels all pending IRPs, queued NLBs so imitiating full reset. After process's main thread creates new threads in place of exited threads. But before that, when user thread is terminating (I thing so), the driver faces with destroyed IRPs and crashes. I tried even to do some deley, before terminating user threads, to give time to driver to finish with pending IRPs, but it not helped. In general crashes Send path, when I probe and lock buffers inside queued pending IRP.
Method I use for IRP is METHOD_OUT_DIRECT.
I can not find something about IRP cancellation in NDIS book(doc). Ndis driver has cancel routine for NBLs but I can't find something for IRP cancellation. Who must write cancellation routines for all IRPs issued by user program. How I must cancel pending IRPs from dispatch function of driver. Now I only call IoCancelIRP for all pending IRPs(or IoCompleteRequest). Is it right.
What will be happend, if dispatch function and callback functions of my driver will work in different processors at the same time.
Thank You.
Well, hang on. A driver is only allowed to cancel IRPs that it has submitted. You cannot cancel IRPs you are holding that you received from above. That cancellation has to be done by the creator. You can **complete** the IRPs with STATUS_CANCELED, as long as you remember not to touch them after you have completed them.
Yes. Please, say me, if is it possible two symultanineously working procedures of the same driver in different processors, or in the same processor. What procedures of driver can work symultaneously.
Sure, thatâs one of the fun and interesting things about driver programming. You have to KNOW that so you know what data to protect. Multiple user mode threads can certainly requests that reach you simultaneously. This isnât usually a huge problem with drivers that arenât working with hardware, but cancellation can increase the danger. If you have a list of IRPs, for example, then you almost certainly want to protect access to that list with some kind of interlock.
Thank you, mr. Tim. I have protection with spin locks, but I have done it for synchronization(mutual access) between dispatch and callback routines. I couldn't find anything about symultanieously working procedures of driver.
But thatâs all the same thing, right? The ONLY way driver code gets executed is by a dispatch, a callback, or an interrupt.
Why would you terminate threads with the plan of creating new ones to replace them?
Thatâs not your problem, but it is an odd thing to do.
And the implicit answer to Timâs question is that youâre process is not terminating. It is trying to ârestartâ within the same context. If you are rigorous about resource management that can be done, but if not, then you will crash. But no UM crash should ever cause a KM crash unless your driver isnât rigourous
Thank you very much. Before terminating user threads, I'll set an event and wait for the driver to complete all IRP requests. One last question: can the driver reset this event, and how do I do that?
Will IRP requests that the driver has completed but the user has not accepted be cancelled (asynchronous method) or remain in the system as garbage?
One thing is for sure; no KM component should ever fail if the UM side abuses it.
Thatâs true no matter how badly the UM side abuses it. Which also means that âfixingâ a crash in your KM driver by changing the logic in your UM software is not a fix at all.
I guess that English isnât your first language. Thatâs not a problem, but since I speak only English, it might be harder to help you
for sure you need to plan to complete these IRPs. Whether or not the UM component will use the data that you deliver, the KM side canât care. It cannot care. because it operates in an security context that is higher if nothing else
Normally thread creation isnât a cost to be neglected. Usually one plans to create the threads that are needed, or uses one of tjhe thread pool libraries, and if there are errors that you can;t handle, then ABEND and get Windows to give you a new process address space
The easy way is to send an ioctl and have the thread wait on the ioctl to complete.
There is no such thing as user mode âacceptingâ a completed ioctl. Once the driver completes an IRP, it is no longer the kernelâs problem. If the user-mode app chooses to ignore the response, it just gets ignored.
It doesnât seem like good practice, however. Assuming the threads are keeping a list of their outstanding ioctls, just send the âshutdownâ signal and have the thread wait for them all to complete.
Also remember there is the CancelIo user-mode API, which cancels all requests submitted by a single thread on a given file handle. That would put the burden on your driver to watch for the cancellation, such as by using a CancelSafeQueue.
Well, Thank You very much