{"id":100075,"date":"2018-10-29T07:00:00","date_gmt":"2018-10-29T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100075"},"modified":"2019-03-13T00:22:48","modified_gmt":"2019-03-13T07:22:48","slug":"20181029-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20181029-00\/?p=100075","title":{"rendered":"The case of the oplock deadlock poppycock"},"content":{"rendered":"<p>A customer reported that their application would sometimes hang trying to open a file. The call to <code>Create&shy;File<\/code> would simply hang, rather than failing with <code>ERROR_<\/code><code>SHARING_<\/code><code>VIOLATION<\/code> or some other error code. <\/p>\n<p>One case where a <code>Create&shy;File<\/code> can hang is when there is an oplock on the file that needs to be broken. <\/p>\n<p>Explorer takes an oplock on files when generating thumbnails. This allow Explorer to be notified when another application wants access to the file in a manner that conflicts with the the thumbnail extractor, so it can abandon the thumbnail operation and close the file, thereby permitting the other application&#8217;s <code>Create&shy;File<\/code> call to succeed. If Explorer hadn&#8217;t used an oplock, then an application that wants to access the file would get an immediate sharing violation. <\/p>\n<p>The thread that owns the oplock is stuck here: <\/p>\n<pre>\nkernel32!CreateFileW+0x379\nole32!CFileStream::Init_OpenOrCreate+0x10d\nole32!CFileStream::InitWorker+0xb5\nole32!DfFromName+0x8f\nole32!DfOpenDocfile+0x1f2\nole32!DfOpenStorageEx+0x183\nole32!StgOpenStorageEx+0x9d\ncontoso!DllUnregisterServer+0xa9c0\nSHELL32!CIconAndThumbnailOplockWrapper::Extract+0x14\nSHELL32!CShellItem::_GetThumbnail+0x6f\n... and so on ...\n<\/pre>\n<p>The shell took an oplock on the file and then called the thumbnail provider to extract the thumbnail. The thumbnail provider called back into <code>Stg&shy;Open&shy;Storage&shy;Ex<\/code>, presumably to open the file in order to get the thumbnail. But that open call also hung. <\/p>\n<p>The thumbnail extractor passed these flags to <code>Stg&shy;Open&shy;Storage&shy;Ex<\/code>: <\/p>\n<ul>\n<li><code>STGM_<\/code><code>READ&shy;WRITE<\/code><\/li>\n<li><code>STGM_<\/code><code>SHARE_<\/code><code>DENY_<\/code><code>WRITE<\/code><\/li>\n<li><code>STGM_<\/code><code>TRANSACTED<\/code><\/li>\n<\/ul>\n<p>The interesting flag here is <code>STGM_<\/code><code>READ&shy;WRITE<\/code>. The oplock takes read access with deny-write, and the attempt to open the file for writing conflicts with the oplock. This causes the <code>Create&shy;File<\/code> to block waiting for the oplock to be released. But the oplock can&#8217;t be released until the thumbnail extraction is complete. Deadlock. <\/p>\n<p>The customer confirmed that changing <code>STGM_<\/code><code>READ&shy;WRITE<\/code> to <code>STGM_<\/code><code>READ<\/code> fixes the problem. &#8220;But they say that they need write access.&#8221; <\/p>\n<p>We never did learn why the customer requires write access in order to extract a thumbnail from a file. I mean, does that mean that they cannot extract thumbnails from read-only files, or from CD-ROM drives? <\/p>\n<p>We strongly encouraged them to find a way to extract thumbnails that doesn&#8217;t require write access. But if that is impossible for some reason, they can work around it by indicating that their thumbnail extractor is not compatible with oplocks. <\/p>\n<pre>\n[HKEY_CLASSES_ROOT\\CLSID\\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}]\nNoOplock=REG_DWORD:1\n<\/pre>\n<p><strike>For apps packaged with the Desktop Bridge, you can make <a HREF=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/schemas\/appxpackage\/uapmanifestschema\/element-desktop2-desktoppreviewhandler\">this declaration in your manifest<\/a><\/strike>: <\/p>\n<pre>\n<strike>&lt;desktop2:DesktopPreviewHandler ... NoOplock=\"true\"\/&gt;<\/strike>\n<\/pre>\n<p>Correction: The declaration above is for preview handlers, not thumbnail handlers. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Call Sherlock.<\/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":[26],"class_list":["post-100075","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Call Sherlock.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100075","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=100075"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100075\/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=100075"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100075"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100075"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}