[Issue 1360] GC emits HLT when GetThreadContext fails after CreateRemoteThread.

Sean Kelly sean at f4.ca
Sat Jul 21 11:56:01 PDT 2007


d-bugmail at puremagic.com wrote:
> 
> I dont think its a race condition with the thread being created during a
> collection cycle, it happens everytime a GC collect is run (with the exception
> below). 
> 
> This bug had been affecting one of my users for a long time and i could never
> figure out what on his PC was causing it to fail (ended up being some anti
> spyware stuff injecting DLLs like this somewhere along the line). By chance,
> someone had sent me some loader and it was producing the same symptoms that the
> one user was having.
> 
> Long story short: This loader called CreateProcess with CREATE_SUSPENDED flag,
> injected its DLL into the process with CreateRemoteThread, and hit resume.

I think I see the issue.  More below.

> I ended up copying the thread enumeration code out of the gcx function:
> 
> Thread[] threads = Thread.getAll();
> for (uint n = 0; n < threads.length; n++)
> {
>     Thread t = threads[n];
>     if (t && t.getState() == Thread.TS.RUNNING)
>     {
>         display.printf("Thread[%d]: Thread.isSelf() = %d\n", n, t.isSelf());
>         CONTEXT context;
>         context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
>         if (!GetThreadContext(t.hdl, &context))
>             display.printf("GetThreadContext: handle=%08x id=%08x error=%d\n",
> t.hdl, GetCurrentThreadId(), GetLastError());
>     }
> }
> 
> produces the output:
> 
> Thread[0]: Thread.isSelf() = 0
> GetThreadContext: handle=0120 id=00000D50 error=31 (ERROR_GEN_FAILURE)
> 
> I should be doing something like GetThreadId(0x0120) here but its vista only,
> and i'm on XPSP2. Checking with a debugger shows the main thread is 0xd50.
> Assuming the isSelf() isnt failing for another reason, its possible the thread
> the GC consumed as "Main" thread at gc_init is pointing to the
> CreateRemoteThread one or something. 

That's exactly it.  I don't understand why the injected app would be 
initialized within the context of the injecting thread (does this app do 
its initialization manually in DLLMain or something?), but that appears 
to be what's happening.  If you look in std.thread:Thread.thread_init() 
(a routine that's called by gc_init), you can see how a proxy object 
representing the 'main' thread is created.

> I also tried to run a collection cycle in the D programs DLLmain and it worked
> ok. Im not sure if thats just because the stack scanning code wasnt hit, due to
> there being nothing allocated, or from the CreateRemoteThread thread being
> active still or something.

The latter, I think.  And you're saying this is just a plain old D 
application which this is being done to?  I'll admit I really don't 
understand why its C main() routine would be called by the injected 
thread in such a situation, but perhaps I simply haven't read the MS 
docs thoroughly enough yet.  I'll give them another look and see if a 
solution can be found.


Sean


More information about the Digitalmars-d-bugs mailing list