3

I'm working on a huge C++ MFC GUI app using Visual Studio 2010 that's got tons of code the I'm unfamiliar with.

There's a thread that's being spawned way too many times, and I'm not sure where it's being spawned as there's lots of code that spawns this thread. Also, there are many creating points in the code for the same thread. I need to find which creating point started the current thread function.

How can I find where the thread was created in Visual Studio?

Note: I couldn't see where the thread was created in call stack window.

taha
  • 172
  • 8
  • What do you mean by the 'same' thread? What is distinct property of the thread in question? – SergeyA Dec 30 '15 at 15:10
  • Sorry, I mean the same thread id not the same thread. – taha Dec 30 '15 at 15:11
  • try finding thread `pid`. it may help to find thread origin. – roottraveller Dec 30 '15 at 15:12
  • 1
    @taha, sorry, I do not get it. There is only one thread with a given thread id, it can't be 'spawned too many times'. – SergeyA Dec 30 '15 at 15:12
  • @SergeyA, Yes, there is only one thread actually. But there are many thread calls which is not respectively and I can not track the threads. I only need to find which code line created the current thread function. – taha Dec 30 '15 at 15:15
  • Maybe something like this: [Override a function call in C](http://stackoverflow.com/questions/617554/override-a-function-call-in-c). – 001 Dec 30 '15 at 15:21
  • Edit: There many code lines which creates this thread and these code lines are called many times in the run time. – taha Dec 30 '15 at 15:22
  • @rkm_Hodor_king: The OP is well aware of the **process** that spawns this particular thread, just not the specific location in code that does. taha: If you can change the code that creates threads you could assign a name to the thread, containing `__FILE__` and `__LINE__` (see [How to: Set a Thread Name in Native Code](https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx) for details). The thread name is displayed in Visual Studio's *Threads* window. – IInspectable Dec 30 '15 at 15:45

2 Answers2

1

If its possible then make a macro definition for a function which is used for creating threads, then once it is created store thread id/handle in some map which will contain pairs of type: [ThreadID] -> [__FILE__+__LINE__] . This will allow you to check inside your thread where it was created.

a more advanced aproach is to use api hooks, but thats a lot of coding. So you can make use of api hooking with http://codefromthe70s.org/mhook22.aspx and hook CreateThread. When your custom CreateThread function gets executed then you can execute original CreateThread and using its returned handle update a map as in first paragraph. The problem is that you will have to store callstack data to find where this call was executed. You could use http://www.codeproject.com/Articles/11132/Walking-the-callstack for that.

Even with first solution, you might find that __FILE__+__LINE__ does not give you enough information, and a callstack is a must.


I made a small test app with mhook - below is some code that might be useful:

typedef HANDLE(WINAPI *CreateThread_t)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
CreateThread_t fCreateThread = (CreateThread_t)GetProcAddress(LoadLibrary(L"Kernel32.dll"), "CreateThread");

HANDLE
WINAPI
MyCreateThread(
  _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_ SIZE_T dwStackSize,
  _In_ LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_ __drv_aliasesMem LPVOID lpParameter,
  _In_ DWORD dwCreationFlags,
  _Out_opt_ LPDWORD lpThreadId
  )
{
  HANDLE hret = fCreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
  // Here you can add thread entry for hret with current callstack.
  // You will probably want to create this thread suspended, to make
  // sure it wont get executed before map gets updated. Resume it after
  // map update.
  //if (lpStartAddress == MyThreadProcToMonitor) {
    // log things
  //}
  return hret;
}

int main() {
// This will hook create thread
  Mhook_SetHook((PVOID*)&fCreateThread, MyCreateThread);

  // App logic here

  Mhook_Unhook((PVOID*)&fCreateThread);
}
marcinj
  • 48,511
  • 9
  • 79
  • 100
0

If you are allowed to change the code a bit, you could replace the thread-launching calls by a macro that would also log the __FILE__, __LINE__ and thread id, so that you can track the launches.

Ilya
  • 5,377
  • 2
  • 18
  • 33