June, 2010

  • The Old New Thing

    When you set a 100% CPU program to real-time priority, you get what you asked for


    Real-time priority is really dangerous. It's higher priority than nearly everything else. It's higher priority than mouse input, keyboard input, and the disk cache. If you foolishly set the priority class of a CPU-intensive program to real-time, it will suck up your entire processor, leaving no cycles for anything else.

    In particular, since not even input runs at real-time priority, you can't stop it via any interactive means, because the thread that manages input can't even run to process your input.

    Mind you, even if the input thread did run at real-time priority, that wouldn't really help you any. Sure, it could receive your input and distribute it to the appropriate application queues, but those applications are themselves not running with real-time priority, so all that happens is that your input gets quickly transferred to the input queues, where it then sits waiting for the applications to process them (which will never happen since the applications are not running with high enough priority).

    One might argue that Task Manager should run with real-time priority, so it can extricate you from this situation, but that won't help, and it would be wrong. It won't help because you first need to be able to launch Task Manager (or switch to it, if you were prescient enough to have it already running), and none of the ways of launching Task Manager run with real-time priority. (Because nothing in the user interface runs with real-time priority.)

    Second, even if there were a special code path that enabled you to launch Task Manager at real-time priority, it would be wrong, because the fact that Task Manager is running with real-time priority means that it is now stealing CPU cycles from that other process which set itself to real-time priority, which defeats the purpose of that process setting itself to real-time priority in the first place: It set itself to real-time priority because it didn't want anybody stealing CPU time from it!

    What could be done is to have Task Manager display an extra warning dialog when somebody uses it to change a process's priority. The warning dialog would say something like "Fiddling with priority can result in you being totally screwed. Are you sure you want to take this risk?" (Oh wait, that dialog box already exists.) Our friend Igor probably clicked right on past that warning dialog, because he's thinking, "Of course I want to set it to real-time priority, you stupid program, that's why I clicked Real-Time Priority! This is another in a long string of examples of how Windows is one of those coddling operating systems that gets in the way of advanced users like me, throwing up frustrating obstacles which prevent me from getting things done."

    And then he shoots himself in the foot and asks to be coddled a little bit.

  • The Old New Thing

    When you use a term, it helps if you know what the term means


    Some years ago (in a project far, far away) I received a piece of email from a member of the release management team asking me if a particular issue met the escrow reset bug bar or not, as it applied to an upcoming pre-RTM release.

    I asked, "What is the current escrow reset bar?" I thought this was a fair question. After all, in order to state whether or not the issue met the escrow reset criteria, I needed to know what the escrow reset criteria were. I figured they'd reply with something like "The escrow reset criteria are on this internal Web page. Please evaluate the issue against those criteria and get back to us."

    Instead, the response I got back was, "I'm not sure, let me check."

    Some time later, I received the answer.

    There is no formal set of criteria. It's taken on a case-by-case basis after discussion with the team responsible for the issue.

    I thought it was interesting that, first, somebody asked me to evaluate an issue against criteria I was not provided with; second, the person asking the question didn't know the criteria either; and third, it turns out that there were no criteria at all!

    According to their definition, the way to determine whether the issue met the escrow reset bar was to meet with the release management team themselves and let them make the call. In other words, they asked me to make a decision that only they could make.

    They decided not to hold a meeting to discuss the issue. I guess that means it didn't meet the escrow reset bar.

  • The Old New Thing

    Proto-Microspeak: Bug-hugging


    Bug-hugging is the phenomenon of programmers keeping bugs assigned to themselves without actually doing anything to fix them. You typically engage in bug-hugging when there is a bug that you feel strongly should be fixed, but which you also simply haven't gotten around to working on yet. Meanwhile the bug sits and collects dust. You resist allowing the bug to be postponed to the next release because, "We really ought to fix this," and you also resist allowing the bug to be reassigned to another programmer on the team because "Only I know what needs to be done to fix this."

    On the other hand, you are so busy with other things that you never manage to get around to fixing that bug, or because the fix is actually quite complicated and you haven't been able to come up with a big enough stretch of available time to devote to fixing it properly. In some cases, the bug is actually a enormous amount of work, and you don't really want to fix it, but you also can't bear to part with it.

    Think of it as the software version of hoarding. You know in your head that you can't fix it, but in your heart you can't bear to let it go. To put it in the vernacular, you have to piss or get off the pot.

    The behavior is good-intentioned but ultimately harmful to a project shipping on time because it prevents project management from truly understanding how close the project is to being finished, and your affection for the bug prevents them from reassigning it to somebody who has room on his plate to fix it.

    The kicker is that these bugs that are so fiercely held like a security blanket are often ones with relatively low impact, or even feature requests disguised as bugs. "When I do X, then Y, then Z, it would be nice if there was an option to Q directly from the dialog box." Well yeah, it would be nice, but it's not in the product specification, and we have no research data to indicate that adding the Q option to the dialog box won't create confusion or there is a significant body of users who want a Q option on that dialog box in the first place.

    Here is a citation:

    We have a considerable bug backlog here, and it looks like we're about a week behind, but I suspect there's a lot of bug-hugging hiding in these numbers. We plan on working with programmers over the next week to get these numbers to be more realistic.

    The term was coined by a manager here at Microsoft only recently, so it's not really Microspeak yet because it hasn't demonstrated any staying power. I'll file it under Proto-Microspeak.

  • The Old New Thing

    Dum dee dum, just hanging around the European Conference on Computer Supported Co-op... OMG LOOK AT THOSE CUTE DUCKS!


    The 10th European Conference on Computer Supported Co-operative Work was held in Limerick, Ireland, and as you'd expect there were a lot of speakers and breakout sessions and... oh my God, look at those cute ducks!

  • The Old New Thing

    Is it real that you are still using Visual C++ 6 and 5?


    Commenter Sys64738 points out that Bjarne Stroustrup's Web site says that "Literally everything at Microsoft is built using various flavors of Visual C++ - mostly 6.0 and 7.0 but we do have a few holdouts still using 5.0 :-(" and wonders if it's true.

    Well, let's see. Visual C++ 6 came out in 1998 and doesn't support the /GS flag, nor does it support various replacement functions like strcpy_s. This makes it hard for anything compiled with Visual C++ 6 to conform to Microsoft's Security Development Lifecycle which requires all code to be compiled with /GS and bans functions like strcpy.

    As a result, I would suspect that the statement is no longer true. It may have been mostly true when the statement was originally written in the late 1990's, but things have changed a lot since then.

    (The statement wasn't even 100% true when it was written, because Windows 95 used a special version of the compiler not found in nature for selected portions of the operating system.)

    I find it interesting that the fact that the claim appeared on Bjarne Stroustrup's Web site caused the reader to turn off all brain functions responsible for critical evaluation of information. It is unlikely that Mr. Stroustrup has first-hand knowledge of the information on that page; it's almost certainly just a compilation of information reported to him by unnamed sources. (Actually, he even says as much in the opening paragraphs.) And do you honestly think that Visual Studio 2010 is compiled with Visual C++ 6?

  • The Old New Thing

    How do I enable and disable the minimize, maximize, and close buttons in my caption bar?


    A customer was having problems with the small icon that appears in the upper left corner of the caption:

    In my program, I need to enable and disable the Close button programmatically, since the program sometimes goes into a state where I don't want the user to close it. I do this by removing the WS_SYS­MENU style when I want to disable the Close button, and adding it back when I want to re-enable it. However, doing this has as a side effect that the icon for my program doesn't appear in the title bar any more. If I never touch the WS_SYS­MENU style, then it works fine (but then I don't get the enable/disable behavior that I want).

    Okay, the first problem is that you want to disable the Close button. Usability research indicates that users really don't like it when you disable the Close button. It makes them feel trapped and uncomfortable. This is the reason why standard Windows wizards don't provide a way for you to disable the Close button. The user should always have a way out.

    Imagine showing a dialog box saying "By clicking OK, you agree to the following terms," and not having any way for the user to say, "No, thanks." You should leave the Close button enabled, and if the user clicks it at a bad time, you can say, "Okay, I heard you, but I'm right in the middle of something, but once that's done, I'll close."

    Okay, but suppose you're in one of those cases where, really, you need to disable the Close button. You've read the guidelines, you understand why they're there, but you believe that you are an exceptional case.

    If you never want the Close button enabled, then you can just specify the CS_NO­CLOSE style when you register the class.

    To disable the Close button in the caption dynamically, you enable and disable the SC_CLOSE menu item in your system menu.

    void DisableCloseButton(HWND hwnd)
     EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
                    MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
    void EnableCloseButton(HWND hwnd)
     EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
                    MF_BYCOMMAND | MF_ENABLED);

    The other two caption buttons are controlled by window styles:

    void DisableMinimizeButton(HWND hwnd)
     SetWindowLong(hwnd, GWL_STYLE,
                   GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX);
    void EnableMinimizeButton(HWND hwnd)
     SetWindowLong(hwnd, GWL_STYLE,
                   GetWindowLong(hwnd, GWL_STYLE) | WS_MINIMIZEBOX);
    void DisableMaximizeButton(HWND hwnd)
     SetWindowLong(hwnd, GWL_STYLE,
                   GetWindowLong(hwnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
    void EnableMaximizeButton(HWND hwnd)
     SetWindowLong(hwnd, GWL_STYLE,
                   GetWindowLong(hwnd, GWL_STYLE) | WS_MAXIMIZEBOX);

    Why is the close button managed differently from the minimize and maximize buttons?


    Originally, the window caption had only two buttons in the upper right corner, the minimize and maximize buttons, and they were controlled with a window style. Windows 95 added the Close button, but then there was the question of knowing when to enable and disable it. But wait, we already know when to enable and disable it: The application told us when it enabled and disabled the SC_CLOSE menu item. Bingo, just hook up the Close button to the existing menu item (which applications were already in the habit of maintaining), and magic, it just works. No need for applications to write special code to support the Close button. They already wrote the code; they just didn't realize it!

    Exercise: What's wrong with these alternative functions for enabling and disabling the Close button:

    // code in italics is wrong
    void DisableCloseButton(HWND hwnd)
     SetClassLong(hwnd, GCL_STYLE,
                  GetClassLong(hwnd, GCL_STYLE) | CS_NOCLOSE);
    void EnableCloseButton(HWND hwnd)
     SetClassLong(hwnd, GCL_STYLE,
                  GetClassLong(hwnd, GCL_STYLE) & ~CS_NOCLOSE);
  • The Old New Thing

    The voice of Carl Kasell emerges from the loudspeaker as some old guy stands there and moves his mouth


    Some time ago, the NPR news quiz Wait Wait... Don't Tell Me taped a show in Seattle. (They're back in town tonight.) I was fortunate to score tickets to that show, in part because I ordered them nearly a full year before taping. Watching the taping of the show is quite a treat, and I recommend it for any fan of the program. You can watch Peter Sagal pace back and forth as he talks and contrast it to old-school radio man Carl Kasell, who stands perfectly still as he delivers his lines.

    The strangest part of the experience was putting the face to the voice. When Carl Kasell started talking, my reaction was, "Hey, I hear the voice of Carl Kasell, and that old guy on stage is doing a really good job of lip-synching."

    After the show, the on-air talent hung around on stage, and enthusiastic audience members approached the stage to chat, get autographs, and generally be adoring fans. Most of the talent hung around in a group at one end of the stage, but not Carl Kasell. He stood at the other end of the stage, because Carl is special. Whereas the others dealt with a small crowd, the people waiting to see Carl stood patiently in a line. And he also had a bodyguard to facilitate the process.

    You don't expect a public radio news announcer to have a security detail, but that's the level of fame Carl Kasell has risen to.

  • The Old New Thing

    How do I convert an ANSI string directly to UTF-8?


    A customer asked the following question:

    Is there a way to convert an ANSI string directly to UTF-8 string? I have an ANSI string which was converted from Unicode based of the current code page. I need to convert this string to UTF-8.

    Currently I am converting the string from ANSI to Unicode (Multi­Byte­To­Wide­Char(CP_ACP)) and then converting the Unicode to UTF-8 (Wide­Char­To­Multi­byte(CP_UTF8)). Is there a way to do the conversion without the redundant conversion back to Unicode?

    There is no multibyte-to-multibyte conversion function built into Windows (as of this writing). To convert from one 8-bit encoding to another, you have to use Unicode as an intermediate step.

    Fortunately, one of my colleagues chose not to answer the question but instead responded to the question with another question:

    Is the data loss created by the initial conversion to ANSI really acceptable? Convert from the original Unicode string to UTF-8, and you avoid the potential mess introduced by the Unicode-to-ANSI conversion step.

    The customer was puzzled by this data loss remark:

    I'm using the same code page when converting from Unicode to ANSI as I am from converting from ANSI to Unicode. Will there still be a data loss?

    None of the code pages which Windows supports as an ANSI code page can express the full repertoire of Unicode characters. It's simple mathematics: Since one of the requirements for being an ANSI code page is that no single character can be more than 2 bytes, there simply isn't enough expressive power to encode all of Unicode. Now, if you're lucky, all of the characters you're encoding will exist in the ANSI code page, and they will survive the round trip, but that's just if you're lucky.

    It's like converting an image from 32-bit color to 8-bit color via the halftone palette. The palette is the "code page" for the conversion. Remembering to use the same palette when converting back is an essential step, but the result of the round trip will be a degraded image because you can't encode all 32-bit colors in a single 256-color palette. If you're lucky, all the colors in the original image will exist in your palette and the conversion will not result in loss of information, but you shouldn't count on being lucky.

    The customer went on to explain:

    Unfortunately, my code does not have access to the original Unicode string. It is a bridge between two interfaces, one that accepts an ANSI string, and another that accepts a UTF-8 string. I would have to create a new Unicode interface, and modify all existing callers to switch to the new one.

    If all the callers are generating Unicode strings and converting them to ANSI just to call the original ANSI-based interface, then creating a new Unicode-based interface might actually be a breath of fresh air. Keep the poorly-designed ANSI interface around for backward compatibility, so that callers could switch to the Unicode-based interface at their leisure.

    Bonus chatter: Even the round trip from ANSI to Unicode and back to ANSI can be lossy, depending on the flags you pass regarding use of precomposed characters, for example.

  • The Old New Thing

    The giant typewriter eraser in the Olympic Sculpture Park in Seattle


    The Olympic Sculpture Park in Seattle is open and free to the public all year around. (And I'm surprised they haven't gotten the heat from the IOC over use of the word Olympic.)

    One of the works is a giant typewriter eraser. When my friend took her niece (I'm guessing around ten years old at the time) to visit the park, the girl asked, "What's that?"

    Oh, that's a typewriter eraser. Back before Wite-Out or eraser ribbons, this was how you corrected mistakes. This end is the eraser, and you use that end to brush the crumbs off.

    The next question was unexpected, but in retrospect, inevitable.

    "What's a typewriter?"

  • The Old New Thing

    Puzzle: Can you explain this program's crash profile?


    Some time ago, I was asked to help a customer study a set of crashes that had been collected by Windows Error Reporting. (You too can sign up to obtain access to crash data for your application.) The issue itself was the 325th most common crash in the ISV crash database, so fixing it would mean a lot toward improving the overall perceived stability of Windows. Fortunately, the issue was resolved relatively easily, but that's not what made the story interesting. What I found interesting was a little puzzle that faced me when I called up their crash profile.

    One of the items in the crash profile report is a histogram plotting how many crashes per day were reported over the past three months. Most crash profiles take the form of an erratic graph with random day-to-day fluctuations. Sometimes you'll see a gradual trend (for example, as more and more people upgrade to a newer version). But this one had a strong pattern:

    The number of crashes per day remains high for several days, and then plummet for two days, then return to their high values, repeating on a regular cycle.

    It took me a bit of thought, but soon I understood why. Perhaps you can figure it out, too. Hints after the break.

    If you actually stop and count (I didn't; I just eyeballed it), there are five days with high crash frequency, followed by two days with low crash frequency.

    What happens on a seven-day cycle?

    The five days with high crash frequency correspond to Monday through Friday; the two days with low crash frequency correspond to Saturday and Sunday.

    The program in question targets a business audience. People use the program when they're at work (during the work week), but they don't use the program when they're at home (on the weekend). A program that isn't running can't crash.

Page 3 of 4 (32 items) 1234