Enable Detours to be used without allocating or freeing memory while threads are suspended. #261
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Detours uses
new
anddelete
while threads are suspended. This can cause deadlocks if the suspended thread has locked a mutex in the heap. (See issue #70.) Additionally, when AppVerifier is enabled,VirtualFree
andVirtualAlloc
can be hooked by AppVerifier. These hooks do memory operations on the heap internally. The deadlocks are easier to hit when AppVerifier is enabled.Back in 2014, I worked with https://github.com/KnicKnic on a fix for this. We also consulted with https://github.com/galenh on the API design changes. I checked in the fix to a copy of Detours in the Windows repository within Microsoft, but this wasn't propagated back to the Detours master sources. I'm now bringing a cleaned-up version of the fix through GitHub so my code in the Windows repo can switch to the open-source version of Detours.
The fix makes it so all calls to
free
andVirtualFree
are done after all calls toResumeThread
inDetourTransactionAbort
andDetourTransactionCommit
. However, to fully avoid deadlocks, the user needs to also do the following:DetourUpdateThread
to the newDetourUpdateThreadPreallocated
API.DetourAttach
,DetourAttachEx
, andDetourDetach
before callingDetourUpdateThreadPreallocated
in a given transaction.DetourUpdateThreadPreallocated
and the call toDetourTransactionAbort
orDetourTransactionCommit
.If you follow those rules, you will avoid memory allocations while threads are suspended in the process.
The
DetourUpdateThreadPreallocated
API is likeDetourUpdateThread
except the user passes in aDETOUR_THREAD_DATA
struct that they allocated themselves ahead of time. The user is responsible for freeing the memory after aborting or committing the transaction. In my code, I store theDETOUR_THREAD_DATA
instances in astd::vector
that I resize ahead of time in order to front-load the allocation before starting the detour transaction.Microsoft Reviewers: Open in CodeFlow