{"id":1000,"date":"2009-07-31T09:17:07","date_gmt":"2009-07-31T07:17:07","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=1000"},"modified":"2009-07-31T09:40:45","modified_gmt":"2009-07-31T07:40:45","slug":"xvid-encoder-and-windows-messages-from-a-worker-thread","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/1000","title":{"rendered":"XviD video encoder and window messages from a worker thread"},"content":{"rendered":"<p>While encoding video, <a href=\"http:\/\/www.xvid.org\/\">Xvid Video Encoder<\/a> provides an optional status window displaying information on encoding progress.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1001\" title=\"Xvid Encoder Status Window\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image001.png\" alt=\"Xvid Encoder Status Window\" width=\"494\" height=\"385\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image001.png 494w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image001-320x249.png 320w\" sizes=\"auto, (max-width: 494px) 100vw, 494px\" \/><\/p>\n<p>Since streaming typically takes place in a worker thread, with possibly no windows at all, and no message pump, the window is to be created on GUI thread and the encoder needs to synchronize progress updates with the window.<\/p>\n<p>Such synchronization is a typical point where a deadlock can occur. Carelessly a window message may be sent in a blocking way so that worker thread is waiting while the message is processed on the window thread. If this sending happens at the moment of GUI thread trying to stop worker thread, a deadlock takes place. This problem often comes up when message sending takes place indirectly, e.g. being wrapped by an API call, such as <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms633546%28VS.85%29.aspx\">SetWindowText<\/a>, or as it can be seen below <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb761879%28VS.85%29.aspx\">IsDlgButtonChecked<\/a>.<\/p>\n<p>In order to avoid deadlocks one should never <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms644950%28VS.85%29.aspx\">SendMessage<\/a> from a worker thread. Instead there should be a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms644944%28VS.85%29.aspx\">PostMessage<\/a> with possibly a wait function which waits for either synchronization event (set by window) or worker thread termination request:<\/p>\n<pre><span style=\"color: #800080;\">{<\/span>\r\n  CLock Lock<span style=\"color: #808030;\">(<\/span>m_CriticalSection<span style=\"color: #808030;\">)<\/span><span style=\"color: #800080;\">;<\/span>\r\n  m_sText <span style=\"color: #808030;\">=<\/span> sText<span style=\"color: #800080;\">;<\/span>\r\n  m_SynchronizationEvent<span style=\"color: #808030;\">.<\/span>Reset<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #800080;\">;<\/span>\r\n<span style=\"color: #800080;\">}<\/span>\r\n<span style=\"color: #400000;\">PostMessage<\/span><span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #800080;\">;<\/span>\r\n<span style=\"color: #603000;\">HANDLE<\/span> phObjects<span style=\"color: #808030;\">[<\/span><span style=\"color: #808030;\">]<\/span> <span style=\"color: #808030;\">=<\/span> <span style=\"color: #800080;\">{<\/span> ThreadTerminationEvent<span style=\"color: #808030;\">,<\/span> m_SynchronizationEvent <span style=\"color: #800080;\">}<\/span><span style=\"color: #800080;\">;<\/span>\r\n<span style=\"color: #800000; font-weight: bold;\">const<\/span> <span style=\"color: #603000;\">DWORD<\/span> nWaitResult <span style=\"color: #808030;\">=<\/span>  <span style=\"color: #400000;\">WaitForMultipleObjects<\/span><span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">,<\/span> phObjects<span style=\"color: #808030;\">,<\/span> <span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">.<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #800080;\">;<\/span>\r\n<span style=\"color: #800000; font-weight: bold;\">if<\/span><span style=\"color: #808030;\">(<\/span>nWaitResult <span style=\"color: #808030;\">=<\/span><span style=\"color: #808030;\">=<\/span> WAIT_OBJECT_0 <span style=\"color: #808030;\">+<\/span> <span style=\"color: #008c00;\">1<\/span> <span style=\"color: #808030;\">)<\/span> <span style=\"color: #696969;\">\/\/ m_SynchronizationEvent<\/span>\r\n<span style=\"color: #800080;\">{<\/span>\r\n  CLock Lock<span style=\"color: #808030;\">(<\/span>m_CriticalSection<span style=\"color: #808030;\">)<\/span><span style=\"color: #800080;\">;<\/span>\r\n  <span style=\"color: #696969;\">\/\/ ...<\/span>\r\n<span style=\"color: #800080;\">}<\/span><\/pre>\n<p>Back to Xvid encoder: trying to abort encoding process, the application deadlocks. Thread checking shows worker thread state:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1002\" title=\"Xvid Video Encoder Deadlocked Thread Call Stack\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image002.png\" alt=\"Xvid Video Encoder Deadlocked Thread Call Stack\" width=\"517\" height=\"322\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image002.png 517w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2009\/07\/31-image002-320x199.png 320w\" sizes=\"auto, (max-width: 517px) 100vw, 517px\" \/><\/p>\n<p>That is, a described deadlock in action.<\/p>\n<p>While it is already made this way letting deadlock occur, is there any workaround to avoid locking? Yes, there is. Stopping encoding, GUI thread should keep pumping messages while waiting for worker thread termination. Before closing worker thread handle, one needs to signal the thread to terminate and wait using thread handle with <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms684242%28VS.85%29.aspx\">MsgWaitForMultipleObjects<\/a>, so that messages possibly sent while terminating the thread are dispatched to target windows.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While encoding video, Xvid Video Encoder provides an optional status window displaying information on encoding progress. Since streaming typically takes place in a worker thread, with possibly no windows at all, and no message pump, the window is to be created on GUI thread and the encoder needs to synchronize progress updates with the window.&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/1000\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,10],"tags":[174,233,231,235,236,238,237,234,486,232,230],"class_list":["post-1000","post","type-post","status-publish","format-standard","hentry","category-seriously","category-video","tag-compression","tag-deadlock","tag-encoder","tag-message","tag-msgwaitformultipleobjects","tag-postmessage","tag-sendmessage","tag-synchronization","tag-video","tag-windowing","tag-xvid"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1000","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=1000"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1000\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=1000"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=1000"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=1000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}