February, 2010

  • The Old New Thing

    What is the maximum length of an environment variable?

    • 25 Comments

    A customer noticed that environment variables were being truncated at 2047 characters and wanted to know what the maximum length of an environment variable is.

    This is one of those cases where you can answer the customer's question or you can try to answer the question the customer is really asking. If you just answer the question, you're doing the customer a disservice.

    The theoretical maximum length of an environment variable is around 32,760 characters. However, you are unlikely to attain that theoretical maximum in practice.

    All environment variables must live together in a single environment block, which itself has a limit of 32767 characters. But that count is the sum over all environment variable names and values, so you could, I guess, hit that theoretical maximum length if you deleted all the environment variables and then set a single variable called X with that really huge 32,760-character value. In practice, of course, you have to share the environment block with all the other variables in the block, so your random call to SetEnvironmentVariable with a 32,760-character string is unlikely to succeed.

    But that's not your only practical limit.

    It also depends on how you're setting the variable; i.e., the code that your environment-variable-setting technique passes through before it gets to the SetEnvironmentVariable call. If you're using a batch file, then you're constrained by the maximum command line length since the environment variable needs to fit into the command line buffer of the batch processor. On the other hand, maybe you're setting the Environment registry key, in which case you run into a 2048-character limit in the code that parses that registry key and builds an environment block out of it. There's also a limitation in the dialog box for interactively setting environment variables, the numeric value of which I don't happen to know off the top of my head.

    This is one of those skills you have to develop when answering questions from customers: Taking the customer's question and trying to figure out what their real question is.

  • The Old New Thing

    No matter what you do, someone will call you an idiot, part 2

    • 41 Comments

    There was quite a bit of reaction to what I thought was a simple "Hey, here's what's going on" article from last year, specifically on how the Adaptive Display Timeout means that Windows doesn't always start the screen saver exactly on time. As you may recall, this feature adjusts the time it takes for the screen saver to activate if the user keeps dismissing it immediately after it starts. One of those small things that makes the computer adapt to you rather than vice versa, and an adaptation that you probably don't even notice when it happens.

    I think these two responses below summarize the extremes of the types of reactions this feature generated.

    • Vista/W7 has some nice touches too. http://is.gd/2FgKv Such little things is what we love about Macs.

    • Ich finde das erstaunlich. In einem Linux-System kann man soetwas relativ leicht selber scripten, und sich z.B. einen Button erzeugen, der den Bildschirmschoner kurzzeitig ganz ausschaltet. Sowas geht unter Windows freilich auch, aber kaum ein User kennt das System hinreichend gut. Deshalb stellen sich dort solche Probleme. Erstaunlich.

      Translation: This is incredible. On Linux, you can script this yourself relatively easily and create, for example, a button which completely disables the screen saver for a short time. Admittedly, you can also do this on Windows, but hardly any users know the system that well. And therefore we have these types of problems. Incredible.

    On the one hand, the feature is something so cool, it must have been stolen from a Mac.

    On the other hand, this feature shows everything that is wrong with Windows. I mean, on Linux, you can solve this problem by simply writing a script!

  • The Old New Thing

    It looks a little like CMD except there is white on the background

    • 27 Comments

    Surely by now you've seen the video where NextGenHacker101 shows you how to use the "Tracer T" program to view "how many IP's are looking at Google", their name, and connection speed (to then to then to then). (And commenter squizz explains why it "worked" in spite of the http prefix.)

    But more awesome is the fact that somebody ported the video to linux!

    Bonus video craziness: It's in Korean but somehow that just adds to the insanity. (Warning: Five minutes of your life you will never get back.)

    The comments on the YouTube video identify the song as "Bo Peep Bo Peep <- possibly the most addictive/annoying song ever."

  • The Old New Thing

    How many servings are there in a single-serve cup? The answer might surprise you

    • 42 Comments

    I was in the grocery store, and there was a sign advertising a new product.

    Delight in a cup
    Your favorite XYZ Ice Cream
    Now in convenient single-serve cups.

    I took a look at the cup. Seemed kind of big for a single serving. I picked one up to read the nutritional information.

    Servings per container: 2
  • The Old New Thing

    How do I get information about the target of a symbolic link?

    • 26 Comments

    Functions like GetFileAttributes and FindFirstFile, when asked to provide information about a symbolic link, returns information about the link itself and not the link destination. If you use the FindFirstFile function, you can tell that you have a symbolic link because the file attributes will have the FILE_ATTRIBUTES_REPARSE_POINT flag set, and the dwReserved0 member will contain the special value IO_REPARSE_TAG_SYMLINK.

    Okay, great, so now I know I have a symbolic link, but what if I want information about the link target? For example, I want to know the size of the link target, its last-modified time, and its name.

    To do this, you open the symbolic link. The I/O manager dereferences the symbolic link and gives you a handle to the link destination. You can then call functions like GetFileSize, GetFileInformationByHandleEx, or GetFinalPathNameByHandle to obtain information about the symbolic link target.

    Exercise: If the field is called dwReserved0, shouldn't it be off limits? Why isn't the field called dwReparsePointType?

  • The Old New Thing

    Advocating the overthrow of the government of the United States by force or subversion

    • 43 Comments

    It has been widely reported that South Carolina now requires "subversive groups" to register with the Secretary of State (and pay a $5 filing fee).

    Curiously, the list of organizations which must register include "an organization subject to foreign control." I wonder if this means that all consulates have to register, and that when any foreign dignitary visits South Carolina, they have to pay a $5 filing fee. (Not to mention all foreign-owned companies like Shell Oil.)

    Actually, it has been pointed out that a "subversive organization" includes one which advocates, teaches, or practices the propriety of controlling the government of the United States. I guess this means all political parties are subversive organizations. (Something most of us knew already.)

    And apparently, in your registration, you also have to include the bylaws or minutes of meetings from the last year. I wonder whether you have to resubmit the minutes each year. I'm sure somebody could keep a government bureaucrat busy for a long time by submitting hundreds of pages of "minutes".

    Anyway, this is a long and largely superfluous set-up for a different story. The mother of a colleague of mine came to visit from Canada. For some reason, the United States requires visitors to fill out a questionnaire asking them whether they are a drug dealer, whether they are a Nazi war criminal, and this question:

    Do you advocate the overthrow of the United States government by force or subversion?

    The sweet old lady studied the question for a while, then circled force.

    Bonus weirdness: On the form, it also says "Answering Yes will not necessarily exclude you from admission to the United States."

  • The Old New Thing

    Microwave popcorn enthusiast proudly proclaims, "I *am* popcorn!"

    • 19 Comments

    Oscar Night is a few weeks away, but when you settle in to watch the show with your bowl of popcorn, please be aware that inhaling deeply from the fumes of a freshly-opened bag of microwave popcorn is not the greatest decision you can make from a health standpoint. (Then again, you probably ought to reconsider eating microwave popcorn in the first place, but let's leave that aside.)

    A disease informally known as popcorn lung afflicts people who work in popcorn factories and has been known since 2002. But in 2007, doctor diagnosed the first case of popcorn lung in an end-user. The risk is not from eating the popcorn but from breathing it. "This patient described enjoying the smell so much he was actually inhaling the steam." The best part of the article was when the patient was asked, "Are you around a lot of popcorn?"

    The response: "I am popcorn."

    Update: Oscar Night is not actually this weekend. That's what happens when you schedule your blog entries over a year in advance and have to guess when Oscar Night is coming.

  • The Old New Thing

    For better performance, set all your monitors to the same color format

    • 29 Comments

    Pplu wonders why programs run more slowly when the system is running with multiple monitors.

    Well, for one thing, of course, when you have more than one monitor, there's more stuff on the screen for the system to keep track of. It's the same reason that programs run more slowly on a large monitor than on a small monitor.

    And if there's only one monitor, then functions like MonitorFromPoint become trivial if the flag is something like MONITOR_DEFAULTTONEAREST, because when there's only one monitor, answering questions like "What monitor is closest to this point"? becomes very easy.

    If your two monitors are not the same dimensions, then the union of the two monitors will not be rectangular, which makes clipping against the union of all monitors more complicated.

    But I suspect the big penalty for multiple monitors kicks in if you make the mistake of setting your monitors to different color formats, for example, if you set one monitor to 565 format and set another to 24bpp.

    If the two monitors do not use the same color format, then programs will be forced to use DIBs instead of DDBs for screen bitmaps, in case a window is moved to a window with a different color format (or worse, is positioned so it straddles two monitors with different color formats). In principle, programs need only use the "worst-case" DIB; for example, if one monitor is 555 and the other is 565, then a 565 DIB will suffice. In practice, however, most programs just fall back to a 24bpp or 32bpp DIB when faced with monitors with different color formats.

    (You query whether all monitors have the same color format by calling GetSystemMetrics(SM_SAMEDISPLAYFORMAT).)

    Since a format conversion takes place when a DIB is blitted to a device with a different color format, forcing a program to retain its bitmaps as DIBs means that for at least one of the monitors (and probably both), you're going to undergo a format conversion when that DIB is drawn to the screen. There are also a few miscellaneous optimizations which are disabled when not all your monitors use the same color format because the cost of using DIBs outweighs the savings from the optimization.

    So if you haven't already, go into your display settings and check that you set all your monitors to the same color depth. If you don't do this, then a large class of graphics optimizations is lost.

  • The Old New Thing

    A simple Venn diagram teaches you the difference between Norway and Sweden

    • 12 Comments

    Not sure it helps, though.

  • The Old New Thing

    It's fine to use fibers, but everybody has to be on board with the plan

    • 13 Comments

    We saw fibers a long time ago when I looked at how you can use fibers as a form of coroutines to simplify the writing of enumerators. A fiber is a handy tool, but it's a tool with very sharp edges.

    Since fibers are promiscuous with threads, you have to be careful when running code that cares about what thread it is running on, because that code may discover that its thread changed out from under it.

    For example, critical sections and mutexes remember which thread owns them. If you enter a critical section on a fiber, and then you unschedule the fiber, then reschedule it onto a different thread, and then you leave the critical section, your critical section will end up corrupted because you broke the rule that says that a critical section must be exited on the same thread that entered it.

    Actually, you were already in bad shape once you unscheduled the fiber while it owned a resource: An unscheduled fiber cannot release the resource. Unscheduling a fiber is like suspending a thread: Anybody who later waits for that fiber to do anything will be waiting for an awful long time, because the fiber isn't running at all. The difference, though, is that the fiber is unscheduled at controlled points in its execution, so you at least have a chance at suspending it at a safe time if you understand what the fiber is doing.

    For example, suppose you enter a critical section on a fiber, and then unschedule the fiber. Some time later, a thread (either running as a plain thread or a thread which is hosting a fiber) tries to enter the critical section. One of two things can happen:

    1. The thread happens to be the same one that was hosting the fiber that entered the critical section. Since a thread is permitted to re-enter a critical section it had previously acquired, the attempt to enter the critical section succeeds. You now have two chunks of code both running inside the critical section, which is exactly what your critical section was supposed to prevent. Havoc ensues.
    2. The thread happens to be different from the one that was hosting the fiber that entered the critical section. That thread therefore blocks waiting for the critical section to be released. But in order for that to happen, you have to reschedule the owning fiber on its original thread so it can exit its protected region of code and release the critical section.

    More generally, if you use an object which has thread affinity on a fiber, you are pretty much committed to keeping that fiber on that thread until the affinity is broken.

    This affinity can be subtle, because most code was not written with fibers in mind. Any code which calls TlsGetValue has thread affinity, because thread local storage is a per-thread value, not a per-fiber value. (This also applies to moral equivalents to TlsGetValue, like code which calls GetCurrentThreadId and uses it as a lookup key in a table.) You need to use FlsGetValue to get values which follow fibers around. But on the other hand, if the code is not running on a fiber, then you can't call FlsGetValue since there is no fiber to retrieve the value from. This dichotomy means that it's very hard if not impossible to write code that is both thread-safe and fiber-aware if it needs to store data externally on a per-thread/fiber basis. Even if you manage to detect whether you are running on a thread or a fiber and call the appropriate function, if somebody calls ConvertThreadToFiber or ConvertFiberToThread, then the correct location for storing your data changed behind your back.

    If you are calling into code that you do not yourself control, then in the absence of documentation to the contrary, you don't really have enough information to know whether the function is safe to call on a fiber. For example, C runtime functions like strcmp have thread affinity (even though there's nothing obviously threadlike about comparing strings) because they rely on the current thread's locale.

    Bottom line: (similar to the bottom line from last time): You have to understand the code that runs on your fiber, or you may end up accidentally stabbing yourself in the eyeball.

    Bonus chatter: Structured exception handling is fiber-safe since it is stack-based rather than thread-based. Note, however, that when you call ConvertThreadToFiber, any active structured exception handling frames on the thread become part of the fiber.

Page 1 of 4 (35 items) 1234