More thoughts on thread naming

I've just finished the first cut of the code that handles the Win32 Thread Naming "API". This means that my debugging tools can now report the name of a thread (if it has been named) rather than just its thread ID. Having implemented the code in the debugger to deal with the exception I find myself wondering about API design and why the original designer of this particular facility decided to make it hard on themselves.

The code that I've written to handle the exception is made more complex by the fact that the "API" doesn't pass the length of the name. It could, it passes other stuff and the length would be an easy thing to pass. Since we don't know the length we need to search for the terminating null character in the name. I may be missing a trick here but since that memory is in the process that's being debugged you need to use ReadProcessMemory() to look at it. To be on the safe side you should probably use VirtualQueryEx() to check the validity of reading from the page in which the data resides. Since we have no idea how long the block of memory is that we want to read from I work out the amount of memory that exists in the page in which the supplied pointer points after the point to which we're pointing and then read all of that (which is probably much too much). Once I've read that I scan along looking for the null byte that terminates the string... Of course if the string happens to span pages then you need to read the whole of the next page and continue your scan...


As I said, perhaps I'm being a numpty here. Since whoever designed this facility probably had to write the debugger side of things it makes you wonder why they did it this way. It's SO much easier to deal with the OutputDebugString() debug event since we get the pointer to the data and the length of the data...


I guess the thread naming 'api' could come from the pre windows NT days... Back when the debugger could poke around with another processes memory as it it were its own...

The complexity of reading, verifying and caching memory from the other process must be handled by the native debugger to make stack walking, and expression evaluation efficient in the remote debugging case. The dev who made this 'api' choice actually was using the simplest approach given the task at hand, and the services already available in the native debugger implementation.


Ok, sounds fair enough, I can imagine a more efficient version of my code that relies on a table of validated pages that it can use to predetermine the data it can read in the target process. But... Why the difference in how the OutputDebugString debug event works? Surely it's always more efficient to be passed the length, even if you're caching the page information from the target process and even if you distrust the length you're given...

You are certainly correct that including the size makes the debugger side simpler, as well as being more consistent with OS originated debug events. My intention was merely to point out why the choice didn't make the task harder for the Dev who made it.

Fair enough :)

Leave a comment