Is referencing a file by handle blocking?

Hi,

I wonder whether ObReferenceObjectByHandle() is a blocking operation. Querying the name of a mailslot or pipe can be blocking (thanks to the timeouts if another operation is ongoing), so I need to find out (using the file object flags) whether the file object describes a pipe of mailslot.

Any hints are welcome, thanks!

Oliver

PS: DDKWizard has been updated recently - http://ddkwizard.assarbad.net/


May the source be with you, stranger :wink:

ICQ: #281645
URL: http://assarbad.info | http://windirstat.info | http://blog.assarbad.info

> I wonder whether ObReferenceObjectByHandle() is a blocking operation

So, you wonder whether the caller may be put in a wait state. The answer is
Yes.

–
Slava Imameyev, xxxxx@hotmail.com

ā€œOliver Schneiderā€ wrote in message
news:xxxxx@ntdev…
> Hi,
>
> I wonder whether ObReferenceObjectByHandle() is a blocking operation.
> Querying the name of a mailslot or pipe can be blocking (thanks to the
> timeouts if another operation is ongoing), so I need to find out (using
> the file object flags) whether the file object describes a pipe of
> mailslot.
>
> Any hints are welcome, thanks!
>
> Oliver
>
> PS: DDKWizard has been updated recently - http://ddkwizard.assarbad.net/
> –
> ---------------------------------------------------
> May the source be with you, stranger :wink:
>
> ICQ: #281645
> URL: http://assarbad.info | http://windirstat.info |
> http://blog.assarbad.info
>
>

> I wonder whether ObReferenceObjectByHandle() is a blocking operation

I don’t see how ObRefObjByHandle can ā€œblockā€ the caller (that is, cause the current thread to voluntarily relinquish control of the CPU as in waiting for a mutex)… assuming that’s the question.

The Object Manager references the handle table, looks the handle up, checks the mask of granted access, and (if the access is granted) increments the reference count and then derefs the handle table.

The handle table ref/deref is just for rundown protection.

I don’t see how this can cause a wait.

Of course, it’s entirely possible that I’m missing something…

Peter
OSR

You didn’t miss anything. It works as you describe and is not affected by currently pended i/o or how the file handle was opened. It is basically a table lookup, type check, and then ref.

d

> You didn't miss anything. It works as you describe and is not affected

by currently pended i/o or how the file handle was opened. It is
basically a table lookup, type check, and then ref.

Thanks Slava, Peter and Doron!

@Slava: Actually my question was probably not expressed very well. I was referring to pending I/O as Doron phrased it.

Oliver


May the source be with you, stranger :wink:

ICQ: #281645
URL: http://assarbad.info | http://windirstat.info | http://blog.assarbad.info

>The Object Manager references the handle table, looks the handle up,

…
I don’t see how this can cause a wait.

The handle table entry must be locked, this might results in calling
KeStallExecutionProcessor or KeWaitForSingleObject if the table entry has
been locked by another thread.
So the procedure blocks the caller if the entry has been locked, i.e. calls
the scheduler explicitly.
P.S. Also, ObReferenceObjectByHandle calls the code that might be baged out,
this also results in calling the scheduler.

wrote in message news:xxxxx@ntdev…
>> I wonder whether ObReferenceObjectByHandle() is a blocking operation
>
> I don’t see how ObRefObjByHandle can ā€œblockā€ the caller (that is, cause
> the current thread to voluntarily relinquish control of the CPU as in
> waiting for a mutex)… assuming that’s the question.
>
> The Object Manager references the handle table, looks the handle up,
> checks the mask of granted access, and (if the access is granted)
> increments the reference count and then derefs the handle table.
>
> The handle table ref/deref is just for rundown protection.
>
> I don’t see how this can cause a wait.
>
> Of course, it’s entirely possible that I’m missing something…
>
> Peter
> OSR
>
>

It MIGHT, but that’s not the way the code is written as far as I can tell. At least not in XP and not in Vista. It’s actually the handle table itself that’s locked, not the handle table entry. But in any case, that’s why I tried to be clear about the type of handle table lock that’s acquired: It’s a Rundown protection lock. This does not block, but rather if there’s a rundown in progress the attempt to lock the handle table will fail, and thus the overall request will fail.

Obviously, but that wasn’t the question. However, in fact, on any practical Windows system even THIS won’t really happen. The code for the OS will be in a Large Page, and that’s not going to get paged out.

Again, it’s always possible that I’m wrong… but I don’t see how.

Peter
OSR

W2k and NT call KeWaitForSingleObject while locking the hash table entry,
and I assume that XP calls KeWaitForSingleObject in ExfUnblockPushLock for
the push lock that is used to lock _HANDLE_TABLE.
The following for XP SP2 installed on my laptop,
ObReferenceObjectByHandle calls ExMapHandleToPointerEx. Then
ExMapHandleToPointerEx calls ExpLookupHandleTableEntry then checks for NULL
and calls ExpBlockOnLockedHandleEntry if InterlockedCompareExchange failed.
ExpBlockOnLockedHandleEntry calls ExBlockPushLock( PushLock,
WaitBlockAllocateOnStack ) and then ExfUnblockPushLock( PushLock,
WaitBlockAllocateOnStack ) with the non NULL wait block and it seems that
the wait bit is set. In ExfUnblockPushLock I see a call to
KeWaitForSingleObject with NULL Timeout if the wait block is not NULL and
another thread is now executing( or has already executed ) the loop for all
_EX_PUSH_WAIT_BLOCKs to set _EX_PUSH_WAIT_BLOCK->WakeEvent in a signal
state.
Am I wrong?

wrote in message news:xxxxx@ntdev…
>


>
> It MIGHT, but that’s not the way the code is written as far as I can tell.
> At least not in XP and not in Vista. It’s actually the handle table
> itself that’s locked, not the handle table entry. But in any case, that’s
> why I tried to be clear about the type of handle table lock that’s
> acquired: It’s a Rundown protection lock. This does not block, but rather
> if there’s a rundown in progress the attempt to lock the handle table will
> fail, and thus the overall request will fail.
>
>


>
> Obviously, but that wasn’t the question. However, in fact, on any
> practical Windows system even THIS won’t really happen. The code for the
> OS will be in a Large Page, and that’s not going to get paged out.
>
> Again, it’s always possible that I’m wrong… but I don’t see how.
>
> Peter
> OSR
>

No, in fact you are entirely right… and I stand humbly corrected.

My reading of the code is slightly different (easily explained by different versions of the OS), but you’re essential thesis is correct: There is potentially a wait for a pushlock in the code path.

Thanks for being sufficiently tennacious to ā€œproveā€ this. Bravo!

Peter
OSR

> I wonder whether ObReferenceObjectByHandle() is a blocking operation.

No. It is not the name query.

–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

> The handle table entry must be locked, this might results in calling

KeStallExecutionProcessor or KeWaitForSingleObject if the table entry has
been locked by another thread.
So the procedure blocks the caller if the entry has been locked, i.e. calls
the scheduler explicitly.

This is not important.

ā€œBlockingā€ is only important in Windows - unlike Linux - in term that you
cannot block the thread for a long time in dispatch routine
, especially you
cannot block the thread till the conditions will occur to complete the IRP. You
must go the STATUS_PENDING way instead.

The reason is that such blocking effectively kills the idea of overlapped IO
and IO completion ports, so, no driver can do this.

It is safe to block in dispatch routine, though, if IoIsOperationSynchronous
returns TRUE. NOTE: this routine requires a valid file object in the IRP stack
location, BSOD otherwise, so, it cannot be used in storage stacks.

In the OP’s case - referencing the file object can only block for a tiny amount
of time to access the table. So, it is OK.

–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

I suspected that smb argues that this routine can ā€œblock for a tiny amount
of timeā€, this is not relevant to our discussion, the matter was- whether
the thread can voluntary put itself in a wait state and voluntary relinquish
the CPU.
Also, give a criteria of ā€œtiny amountā€. Is the blocking in a page fault
handler called to load a handles table is ā€œa tiny amountā€? Is waiting in the
push lock release routine is ā€œa tiny amountā€?

–
Slava Imameyev, xxxxx@hotmail.com

ā€œMaxim S. Shatskihā€ wrote in message
news:xxxxx@ntdev…
>> The handle table entry must be locked, this might results in calling
>> KeStallExecutionProcessor or KeWaitForSingleObject if the table entry has
>> been locked by another thread.
>> So the procedure blocks the caller if the entry has been locked, i.e.
>> calls
>> the scheduler explicitly.
>
> This is not important.
>
> ā€œBlockingā€ is only important in Windows - unlike Linux - in term that you
> cannot block the thread for a long time in dispatch routine
, especially
> you
> cannot block the thread till the conditions will occur to complete the
> IRP. You
> must go the STATUS_PENDING way instead.
>
> The reason is that such blocking effectively kills the idea of overlapped
> IO
> and IO completion ports, so, no driver can do this.
>
> It is safe to block in dispatch routine, though, if
> IoIsOperationSynchronous
> returns TRUE. NOTE: this routine requires a valid file object in the IRP
> stack
> location, BSOD otherwise, so, it cannot be used in storage stacks.
>
> In the OP’s case - referencing the file object can only block for a tiny
> amount
> of time to access the table. So, it is OK.
>
> –
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>

> Also, give a criteria of ā€œtiny amountā€. Is the blocking in a page fault

handler called to load a handles table is ā€œa tiny amountā€?

Are you sure that the handle table is pageable?

–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

> Are you sure that the handle table is pageable?

I think yes, it would be waste of physical memory to save all handle table
entries in nonpaged memory. A process can have up to 256*256*256 handles(
each handle table entry > 8 byte ), so saving all handle entries in the
nonpaged memory would be a really waste of memory.

–
Slava Imameyev, xxxxx@hotmail.com

ā€œMaxim S. Shatskihā€ wrote in message
news:xxxxx@ntdev…
>> Also, give a criteria of ā€œtiny amountā€. Is the blocking in a page fault
>> handler called to load a handles table is ā€œa tiny amountā€?
>
> Are you sure that the handle table is pageable?
>
> –
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>

I believe the functions that manipulate the handle table are marked pagable. I don’t know for certain whether the data structures are, but they probably are, and even if they aren’t, pagable code is enough.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Wednesday, December 27, 2006 3:07 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Is referencing a file by handle blocking?

Also, give a criteria of ā€œtiny amountā€. Is the blocking in a page fault
handler called to load a handles table is ā€œa tiny amountā€?

Are you sure that the handle table is pageable?

–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer