{"id":43943,"date":"2014-10-01T07:00:00","date_gmt":"2014-10-01T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/10\/01\/you-can-name-your-car-and-you-can-name-your-kernel-objects-but-there-is-a-qualitative-difference-between-the-two\/"},"modified":"2014-10-01T07:00:00","modified_gmt":"2014-10-01T07:00:00","slug":"you-can-name-your-car-and-you-can-name-your-kernel-objects-but-there-is-a-qualitative-difference-between-the-two","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141001-00\/?p=43943","title":{"rendered":"You can name your car, and you can name your kernel objects, but there is a qualitative difference between the two"},"content":{"rendered":"<p>\nA customer reported that the\n<code>Wait&shy;For&shy;Single&shy;Object<\/code>\nappeared to be unreliable.\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nWe have two threads, one that waits on an event and the other\nthat signals the event.\nBut we found that sometimes, signaling the event does not wake\nup the waiting thread.\nWe have to signal it twice.\nWhat are the conditions under which\n<code>Wait&shy;For&shy;Single&shy;Object<\/code>\nwill ignore a signal?\n<\/p>\n<pre>\n<i>\/\/ cleanup and error checking elided for expository purposes\nvoid Thread1()\n{\n  \/\/ Create an auto-reset event, initially unsignaled\n  HANDLE eventHandle = CreateEvent(NULL, FALSE, FALSE, TEXT(\"MyEvent\"));\n  \/\/ Kick off the background thread and give it the handle\n  CreateThread(..., Thread2, eventHandle, ...);\n  \/\/ Wait for the event to be signaled\n  WaitForSingleObject(eventHandle, INFINITE);\n}\nDWORD CALLBACK Thread2(void *eventHandle)\n{\n ResetEvent(eventHandle); \/\/ start with a clean slate\n DoStuff();\n \/\/ All the calls to SetEvent succeed.\n SetEvent(eventHandle); \/\/ this does not always wake up Thread1\n SetEvent(eventHandle); \/\/ need to add this line\n return 0;\n}<\/i><\/p><\/blockquote>\n<p>\nRemember, you generally\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/02\/10\/10127054.aspx\">\nshouldn't start with the conspiracy theory<\/a>.\nThe problem is most likely close to home.\n<\/p>\n<p>\nPeople offered a variety of theories as to what may be wrong.\nOne possibility is that some other code in the process is calling\n<code>Reset&shy;Event<\/code> on the event handle.\nAnother is that some other code in the process has a bug where it\nis calling <code>Reset&shy;Event<\/code> on the wrong event handle.\n<\/p>\n<p>\nI asked about the name.\n<\/p>\n<p>\nI have a friend who names her car.\nWhenever she gets a new car,\nshe agonizes over what to call it.\nShe'll drive it for a few days to see what its personality is\nand eventually choose a name that suits the vehicle.\nAnd thereafter, whenever she refers to her car,\nshe uses the name.\n(She also assigns the car a gender.)\n<\/p>\n<p>\nIf you like naming your car, then that's great.\nBut there's a\ndifference between naming your car and naming your kernel objects.\nWhen you give your car a name, that name is just for your private use.\nOn the other hand, if you give your kernel object a name,\nother people can use that name to access your object.\nAnd once they have access to your object,\nthey can do funky things to it,\nlike reset it.\n<\/p>\n<p>\nImagine if you decided to name your car Clara,\nand any time somebody shouted,\n\"Clara, where are you?\"\nyour car horn honked.\nI'm assuming your car has voice recognition software.\nAlso that your car has the personality of a puppy.\nWork with me here.\n<\/p>\n<p>\nEven scarier: Any time somebody shouted,\n\"Clara, open the trunk,\"\nyour car trunk unlocked.\n<\/p>\n<p>\nThat's what happens when you name your kernel objects.\nAnybody who knows the name (and has appropriate access)\ncan open the object and start\ndoing things to it.\nPresumably that's why you named your kernel object in the first place:\nYou <i>want<\/i> this to happen.\nYou gave your object a name specifically to allow other people to\ncome in and access the same object.\n<\/p>\n<p>\nIn the above example, I saw that the event had a very generic-sounding\nname,\n<i>My&shy;Event<\/i>.\nThat sounds like the name that some other similarly uncreative application\ndeveloper might have chosen.\n<\/p>\n<p>\nAnd indeed, that was the reason.\nThere was another application which was creating an event that\ncoincidentally has the same name,\nso instead of creating a new object,\nthe kernel returned a handle to the existing one.\nThe other application called <code>Wait&shy;For&shy;Single&shy;Object<\/code>\non the event,\nand so when the customer's program called\n<code>Set&shy;Event<\/code>,\nit woke the other application instead.\nSo this bug has a double-whammy:\nNot only does it cause your program to miss a signal,\nit causes the other program to receive a signal <i>when it wasn't\nexpecting one<\/i>.\nTwo bugs for the price of one.\n<\/p>\n<p>\nNote that no matter how clever you are at choosing a name for your\nevent,\nyou will always have this problem,\nbecause even if you called it\n<i>Super&shy;Secret&shy;Never&shy;Gonna&shy;Find&shy;It&shy;75<\/i>,\nthere's a program out there that knows the secret name:\nNamely your own program!\nIf you run two copies of your program, they will both be manipulating the\nsame\n<i>Super&shy;Secret&shy;Never&shy;Gonna&shy;Find&shy;It&shy;75<\/i>,\nand then you're back where you started.\nWhen the first copy of the program calls <code>Set&shy;Event<\/code>,\nit may wake up the second copy.\n<\/p>\n<p>\n(This is the same principle behind the conclusion that\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2006\/06\/20\/639479.aspx\">\na single-instance program is its own denial of service<\/a>.)\n<\/p>\n<p>\nKernel objects should not be named unless you intend them to be shared,\nbecause once you name them, you open yourself to\nissues like this.\nIf you name a kernel object,\nit must be because you <i>want<\/i> another process to access it,\nnot because you think giving it a name is kind of cute.\n<\/p>\n<p>\nI suspect a lot of people give their kernel objects names\nnot because they intend them to be shared,\nbut because they see that the <code>Create&shy;Event<\/code>\nfunction has a <code>lpName<\/code> parameter,\nand they think,\n\"Well, I guess giving it a name would be nice.\nMaybe I can use it for debugging purposes or something,\"\nnot realizing that giving it name actually <i>introduced<\/i> a bug.\nAnother possibility is that they see that there is a\n<code>lpName<\/code> parameter and think,\n\"Gosh, I <i>must<\/i> give this event a name.\"\n<\/p>\n<p>\nKernel object names are optional.\nDon't give them a name unless you intend them to be shared.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer reported that the Wait&shy;For&shy;Single&shy;Object appeared to be unreliable. We have two threads, one that waits on an event and the other that signals the event. But we found that sometimes, signaling the event does not wake up the waiting thread. We have to signal it twice. What are the conditions under which Wait&shy;For&shy;Single&shy;Object [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-43943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer reported that the Wait&shy;For&shy;Single&shy;Object appeared to be unreliable. We have two threads, one that waits on an event and the other that signals the event. But we found that sometimes, signaling the event does not wake up the waiting thread. We have to signal it twice. What are the conditions under which Wait&shy;For&shy;Single&shy;Object [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=43943"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43943\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=43943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=43943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=43943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}