DPC Call pattern Question

IS this code pattern correct?

KeInitializeSemaphore(pSem, 0, 1);
KeInitializeDpc(pDpc, func, pBuffer);
KeSetTargetProcessorDpc(pDpc, procNumber);
KeInsertQueueDpc(pDpc, pSem, NULL);
KeWaitForSingleObject(pSem, Executive, KernelMode, FALSE, NULL);

This will wait the thread infinitely for the semaphore (which is being set inside the DPC callback ‘func’, even though the DPCs should fire away almost immediately, what happens if a Unload Request comes to the driver in between?

Will it block on this thread? or will it unload the image without cancelling the DPC potentially causing a BSOD later when the DPC fires on a dangling pointer?

The OS doesn’t take care of your worker threads or DPCs on unload. You can wait for worker threads with KeWaitForSingleObject and you can flush any queued/running DPCs with KeFlushQueuedDpcs

@“Scott_Noone_(OSR)” said:
The OS doesn’t take care of your worker threads or DPCs on unload. You can wait for worker threads with KeWaitForSingleObject and you can flush any queued/running DPCs with KeFlushQueuedDpcs

Totally agree, this came up while reviewing some age old code, which from the looks of it, might be causing BSODs from time to time.

what happens if a Unload Request comes to the driver in between?

Your DrvUnload() routine will get invoked

Will it block on this thread?

No - it is your responsibility to take care of these potential issues . As Scott has pointed out already, the OS does not take care of these things, simply because it has no way of knowing it.

or will it unload the image without cancelling the DPC potentially causing a BSOD later when the DPC fires on a dangling pointer?

It depends on whether there are any outstanding references on the DRIVER_OBJECT. If there are none, your driver’s image may get unloaded immediately after its DrvUnload() routine returns control. Otherwise, the image will stay loaded until its refcount goes down to zero.

Before you start thinking about referencing your DRIVER_OBJECT before creating a thread and dereferencing it immediately before
the thread routine returns control, I am going to remind you that the address that ObDereferenceObject() routine will return control to belongs to the range corresponding to your driver’s code section. Therefore, there is a potential for a race condition if a driver gets unloaded
before ObDereferenceObject() returns control

Anton Bassov