{"id":24553,"date":"2007-11-09T10:00:00","date_gmt":"2007-11-09T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/11\/09\/you-just-have-to-accept-that-the-file-system-can-change\/"},"modified":"2007-11-09T10:00:00","modified_gmt":"2007-11-09T10:00:00","slug":"you-just-have-to-accept-that-the-file-system-can-change","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20071109-00\/?p=24553","title":{"rendered":"You just have to accept that the file system can change"},"content":{"rendered":"<p>\nA customer who is writing some sort of code library\nwants to know how they should implement a function that determines\nwhether a file exists.\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/10\/23\/5612082.aspx\">\nThe usual way of doing this is by calling\n<code>GetFileAttributes<\/code><\/a>,\nbut what they&#8217;ve found is that sometimes\n<code>GetFileAttributes<\/code> will report that a file exists,\nbut when they get around to accessing the file, they get the error\n<code>ERROR_DELETE_PENDING<\/code>.\n<\/p>\n<p>\nThe lesser question is what\n<code>ERROR_DELETE_PENDING<\/code> means.\nIt means that somebody opened the file with\n<code>FILE_SHARE_DELETE<\/code> sharing,\nmeaning that they don&#8217;t mind if somebody deletes the file while\nthey have it open.\nIf the file is indeed deleted, then it goes into &#8220;delete pending&#8221; mode,\nat which point the file deletion\nphysically occurs when the last handle is closed.\nBut while it&#8217;s in the &#8220;delete pending&#8221; state,\nyou can&#8217;t do much with it.\nThe file is in limbo.\n<\/p>\n<p>\nYou just have to be prepared for this sort of thing to happen.\nIn a pre-emptively multi-tasking operating system,\nthe file system can change at any time.\nIf you want to prevent something from changing in the file system,\nyou have to open a handle that denies whatever operation you want\nto prevent from happening.\n(For example, you can prevent a file from being deleted by\nopening it and not specifying <code>FILE_SHARE_DELETE<\/code>\nin your sharing mode.)\n<\/p>\n<p>\nThe customer wanted to know how their &#8220;Does the file exist?&#8221;\nlibrary function should behave.\nShould it try to open the file to see if it is in delete-pending state?\nIf so, what should the function return?\nShould it say that the file exists?\nThat it doesn&#8217;t exist?\nShould they have their function return one of three values\n(Exists, Doesn&#8217;t Exist, and Is In Funky Delete State) instead of a boolean?\n<\/p>\n<p>\nThe answer is that any work you do to try to protect users from this\nweird state is not going to solve the problem because the file system\ncan change at any time.\nIf a program calls &#8220;Does the file exist?&#8221; and the file does exist,\nyou will return <code>true<\/code>,\nand then during the execution of your <code>return<\/code> statement,\nyour thread gets pre-empted and somebody else comes in and puts the\nfile into the delete-pending state.\nNow what?\nYour library didn&#8217;t protect the program from anything.\nIt can still get the delete-pending error.\n<\/p>\n<p>\nTrying to do something to avoid the delete-pending state doesn&#8217;t accomplish\nanything since the file can get into that state\nafter you returned to the caller saying &#8220;It&#8217;s all clear.&#8221;\nIn one of my messages, I wrote that it&#8217;s like fixing a race condition\nby writing\n<\/p>\n<pre>\n\/\/ check several times to try to avoid race condition where\n\/\/ g_fReady is set before g_Value is set\nif (g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp;\n    g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady &amp;&amp;\n    g_fReady &amp;&amp; g_fReady &amp;&amp; g_fReady) { return g_Value; }\n<\/pre>\n<p>\nThe compiler folks saw this message and got a good chuckle out of it.\nOne of them facetiously suggested that they add code to the compiler\nto detect this coding style and not optimize it away.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer who is writing some sort of code library wants to know how they should implement a function that determines whether a file exists. The usual way of doing this is by calling GetFileAttributes, but what they&#8217;ve found is that sometimes GetFileAttributes will report that a file exists, but when they get around to [&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,134],"class_list":["post-24553","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code","tag-things-ive-written-that-have-amused-other-people"],"acf":[],"blog_post_summary":"<p>A customer who is writing some sort of code library wants to know how they should implement a function that determines whether a file exists. The usual way of doing this is by calling GetFileAttributes, but what they&#8217;ve found is that sometimes GetFileAttributes will report that a file exists, but when they get around to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24553","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=24553"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24553\/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=24553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=24553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=24553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}