June, 2012

  • The Old New Thing

    Don't be helpless: What might be the reason for a "Path not found" error?


    Internally at Microsoft, we have a programmer's tool which I will call Program Q. On the peer-to-peer mailing list for Program Q, somebody asked the following question:

    When I try to do a q edit template template_name, instead of opening an editor window where I can modify the template, I get the following error:

    Error opening for write:
    The system cannot find the path specified.

    Can you help resolve this error?

    Okay, there is already everything you need in the error message. The program even converted the error number to error text for you. You just have to read it and think about what it's telling you.

    The file is C:\Users\Waldo\AppData\Local\Temp\2\t144t4.tmp. Therefore the path is C:\Users\Waldo\AppData\Local\Temp\2. I leave you to determine the next step in the investigation.

    That was apparently not enough of a nudge in the right direction.

    While the error message does say "The system cannot find the path specified," the fact remains that I did not specify a path at all. The path in the error message is completely unknown to me. I could try to navigate to that path in Windows Explorer, but I doubt that this has anything to do with resolving the problem.

    Normally, I get an editor window that lets me edit the template, but instead I get this strange error message which I've never seen before.

    I did not try to navigate to the path mentioned in the error message simply because the mentioned Temp folder C:\Users\Waldo\AppData\Local\Temp is completely empty!

    The helplessness is so thick you can cut it with a knife! I also find it astonishing that the person thinks that verifying whether the path can be found is totally unrelated to resolving a "Path not found" error.

    Don't forget, this is a programmer's tool. One should assume that the people who use it have some level of technical skill!

    Okay, first we have a "Path not found" error, and there is a fully-qualified file name whose path couldn't be found. First thing to check is whether the path really exists. From the most recent reply, one can see that the answer is "No, it does not exist." The 2 subdirectory is missing from the Temp directory.

    Okay, so we verified that the error message is valid. The next thing to determine is where the program got this path from. The person already recognized that it was the Temp directory, and it shouldn't be a huge deductive leap to determine that the path probably came from the TEMP or TMP environment variable.

    The observation that the Temp directory is completely empty suggests that the person, in an obsessive-compulsive fit, deleted everything from the Temp directory, including the 2 subdirectory. Too bad that their TEMP environment variable still contained a reference to it.

    As a result, any program that wants to create a temporary file will try to create it in a directory that doesn't exist. Result: "Path not found."

    The fix: Re-create the 2 subdirectory that you mistakenly deleted. (And yes, this fixed the problem.)

    It somehow seemed completely surprising to this person that a "Path not found" error could possibly mean that a path couldn't be found.

  • The Old New Thing

    Microspeak: Turds


    In Microspeak, a turd is a graphics glitch which results in old pixels appearing on the screen when they shouldn't. Perhaps they are not being erased properly, or instead of being erased, they move to an unwanted location. The source of the problem could be failing to mark a region for redrawing after something changed, or it could be that the drawing code ran into a problem and failed to draw over the old pixels. The problem might be that the code whose job it is to remove the object from the screen ran into a problem and didn't actually remove it, resulting in an on-screen object that nobody really is keeping track of. Whatever the reason, these "junk pixels" go by the name turds.

    For non-English speakers: turd is a boorish term for dung.

    The term turds are more generally applied to objects that don't serve any purpose but never got cleaned up. For example, they might be files and registry keys that didn't get deleted when you uninstalled an application, or user accounts for employees who left the company years ago, or C++ objects that some code forgot to delete. If you upgrade your dogfood machine from build to build, there may be files left over from earlier builds that aren't being used by the product any more. A build system may create temporary files that only get erased up when you do a "make clean".

    Note that this particular term turd is not formal Microspeak. You won't find it in a specifications document. But you may encounter it in a bug report or hear it in a casual discussion. Personally, I don't use the term. For the graphics glitches, I prefer to use the word artifact. The leftover stuff that didn't get cleaned up I simply call dirt.

    Bonus chatter: There was one project that actually tried to introduce the word turd as a formal technical term:

    If a transaction has been superseded by another transaction, a marker is left behind in the original transaction record which redirects the resolver to the new transaction. This marker is known as the Transaction Under Redirection Descriptor (TURD).

    I bet the developer who came up with that spent way too much time making up turd-related jokes in other parts of the specification.

  • The Old New Thing

    Why does PrintWindow hate CS_PARENTDC? Because EVERYBODY hates CS_PARENTDC!


    Commenter kero wants to know why the Print­Window function hates CS_PARENT­DC. (And CS_CLASS­DC, and CS_OWN­DC.)

    Because everybody hates CS_PARENT­DC! (And CS_CLASS­DC, and CS_OWN­DC.)

    We saw earlier that these class styles violate widely-held assumptions about how drawing works. I mean, who would have thought that asking for two device contexts would give you the same one back twice? Or that changes to one device context would secretly modify another (because they're really the same)? Or that a window procedure assumes that it will see only one device context ever?

    The Print­Window function is really in a pickle when faced with a window with one of these class styles, because the whole point of Print­Window is to render into some other device context. The Print­Window function says "Render into this other device context, please," and the window acts like a bratty two-year-old who refuses to eat food from anything other than his favorite monkey plate. "This is not my monkey plate. I will now throw a tantrum."

    The Print­Window function passes a custom device context as a parameter to the WM_PRINT message, and the window says, "Hey, no fair! My class styles say that you aren't allowed to pass any old device context; you have to pass mine. I will now take my broccoli and mash it all over the table."

    Oh well. At least it tried.

    Yet another reason to avoid these weird class styles.

  • The Old New Thing

    The time I watched a total lunar eclipse from the top of a mountain


    One of my colleagues loves doing outdoorsy things, and he also loves space and astronomy. Many years ago, he invited a small number of us on an outing that combined both of his interests: A hike up a mountain to view the total lunar eclipse.

    Since an eclipse does not wait until you're ready, it's kind of important to stay on schedule or you'll end up missing the show. We started while it was still light out, and the people who were not seasoned hikers (like me) had to tough it out and keep going, because there was very little time in the schedule for taking breaks. (Because my colleague has been hiking so long that he overestimates the abilities of beginners.)

    We reached the summit in time, and the only other person there was the park ranger, who also had a set of really powerful binoculars he let us use.

    As the moon slipped into the earth's shadow, I stuck my hand into the air and waved it around. I figured this was the best chance I had to cast a shadow on the moon.

    The view, as you might have expected, was spectacular. This was my first viewing of a total eclipse, and I was surprised at how bright orange the moon became at totality.

    The next total lunar eclipse I viewed was from December 2011. It was not a great success. I opted to view the eclipse from my kitchen table rather than from the top of the mountain, and at the moment of truth, the eclipse was not only obscured by clouds, but the moon also dipped behind a stand of trees near my house. So I couldn't see the moon because there were trees blocking the clouds which were blocking the moon, which was of interest only because the earth was blocking it.

  • The Old New Thing

    How do I prefetch data into my memory-mapped file?


    A customer created a memory mapping on a large file and found that when the memory manager wanted to page in data from that file, it did so in 32KB chunks. The customer wanted to know if there was a way to increase the chunk size for efficiency.

    The memory manager decides the chunk size for memory-mapped files, and the chunk size is currently set to eight pages, which on a system with 4KB pages, comes out to 32KB chunks. (Note that this chunk size is an internal parameter and is subject to change in future versions of Windows. I'm telling a story, not providing formal documentation.)

    You have a few options.

    The first option is to switch from memory-mapped files to explicit disk I/O. If you do that, then you have full control over the chunk size. It also means that you have finer control over I/O errors, because you will be told of the error in a controlled manner. As opposed to waiting for the exception to occur, and then carefully parsing the exception to verify that it was in your memory-mapped file region (and not in some other part of the address space), and then trying to unwind out of the exception without crossing any frames that are outside your control.

    Many people decide not to go this route and stick with the memory-mapped file approach, not because they are really good at writing exception handlers and unwinding safely, but because they really like the convenience of memory-mapped I/O, and if something goes wrong with the I/O, they're fine with the program simply crashing. (Of course, there's the group of people who try to write the really clever exception handler and end up making a bigger mess when they mess up.)

    Another option is to go ahead and create your memory-mapped file, but when you are about to do that thing that you want to trigger large-chunk I/O, you can issue sequential Read­File calls from the same file handle into a dummy buffer of, say, 1 megabyte. Do this before you start accessing the memory-mapped version of the file. This will "prefetch" the data off the disk into memory in the large chunks you desire (at a cost of some extra memcpy's).

Page 3 of 3 (25 items) 123