Boost C++ Libraries: Ticket #8613: [Windows] boost::asio::ip::tcp::socket::async_write(boost::asio::null_buffers(), ...) WriteHandler gets a boost::system::error_code with a NULL category pointer on success https://svn.boost.org/trac10/ticket/8613 <p> The <code>boost::asio::ip::tcp::socket::async_write()</code> <a class="missing wiki">WriteHandler</a> gets a <code>boost::system::error_code</code> with a <code>NULL</code> category pointer on success. </p> <p> This is essentially an invalid <code>boost::system::error_code</code> that will cause an access violation when you try to print it has the code doesn't expect the category pointer to be <code>NULL</code>. </p> <p> <code>boost::system::error_code</code> is printed like so: </p> <div class="wiki-code"><div class="code"><pre><span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="n">ec</span><span class="p">.</span><span class="n">category</span><span class="p">().</span><span class="n">name</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;:&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">ec</span><span class="p">.</span><span class="n">value</span><span class="p">();</span> </pre></div></div><p> Which throws an access violation when <code>ec.category()</code> tries to dereference the unexpected NULL category pointer which shouldn't happen. </p> <p> Code that reproduces this problem: </p> <div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/asio.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/bind.hpp&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">ip</span><span class="o">::</span><span class="n">tcp</span><span class="p">;</span> <span class="kt">void</span> <span class="nf">write_handler</span><span class="p">(</span><span class="k">const</span> <span class="n">boost</span><span class="o">::</span><span class="n">system</span><span class="o">::</span><span class="n">error_code</span> <span class="o">&amp;</span> <span class="n">ec</span><span class="p">)</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">ec</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">io_service</span> <span class="n">io_service</span><span class="p">;</span> <span class="n">tcp</span><span class="o">::</span><span class="n">resolver</span> <span class="n">resolver</span><span class="p">(</span><span class="n">io_service</span><span class="p">);</span> <span class="n">tcp</span><span class="o">::</span><span class="n">resolver</span><span class="o">::</span><span class="n">query</span> <span class="n">query</span><span class="p">(</span><span class="s">&quot;www.google.com&quot;</span><span class="p">,</span> <span class="s">&quot;80&quot;</span><span class="p">);</span> <span class="n">tcp</span><span class="o">::</span><span class="n">resolver</span><span class="o">::</span><span class="n">iterator</span> <span class="n">endpoint_iterator</span> <span class="o">=</span> <span class="n">resolver</span><span class="p">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">query</span><span class="p">);</span> <span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">ip</span><span class="o">::</span><span class="n">tcp</span><span class="o">::</span><span class="n">socket</span> <span class="n">socket</span><span class="p">(</span><span class="n">io_service</span><span class="p">);</span> <span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">connect</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">endpoint_iterator</span><span class="p">);</span> <span class="n">socket</span><span class="p">.</span><span class="n">async_write_some</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">null_buffers</span><span class="p">(),</span> <span class="n">boost</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="n">write_handler</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">placeholders</span><span class="o">::</span><span class="n">error</span><span class="p">));</span> <span class="n">io_service</span><span class="p">.</span><span class="n">run</span><span class="p">();</span> <span class="p">}</span> </pre></div></div> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/8613 Trac 1.4.3 chris_kohlhoff Fri, 24 May 2013 02:30:26 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/8613#comment:1 https://svn.boost.org/trac10/ticket/8613#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">worksforme</span> </li> </ul> <p> Works for me. Most likely you have a mismatch in your build options somewhere, e.g. between the boost.system library and your program. </p> Ticket Segev Finer <segev208@…> Fri, 24 May 2013 08:23:55 GMT status changed; resolution deleted https://svn.boost.org/trac10/ticket/8613#comment:2 https://svn.boost.org/trac10/ticket/8613#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">worksforme</span> </li> </ul> <p> Well it definitly doesn't for me... quite consistently... and it's definitly Windows only (as the tag in the ticket name says) </p> <p> Also I'm compiling boost under it's default settings and didn't even change any project settings when I tested this in isolation. </p> <p> heck boost::system works perfectly fine in any other case, it's only when I do a: </p> <div class="wiki-code"><div class="code"><pre><span class="n">socket</span><span class="p">.</span><span class="n">async_write_some</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">asio</span><span class="o">::</span><span class="n">null_buffer</span><span class="p">(),</span> <span class="p">...)</span> </pre></div></div><p> That this issue manifests, with a <code>boost::asio::buffer()</code> it works. </p> <p> I tried debugging this and I think I can see the problem too. </p> <p> <code>async_write_some()/async_send with null_buffer()</code> uses the <code>select_reactor</code> but from what I know and from looking at the code the <code>select()</code> function doesn't use the <code>OVERLAPPED</code> and as such it also doesn't use the embedded <code>OVERLAPPED</code> struct in the <code>win_iocp_operation</code> to store it's result, But when it does <code>post_deffered_completions()</code> on the <code>win_iocp_io_service</code> the service does <code>PostQueuedCompletionStatus()</code> with <code>overlapped_contains_result</code>. </p> <p> This in turn leads to <code>win_iocp_io_service::do_one()</code> using the embedded <code>OVERLAPPED</code> struct in the operation and since it isn't used by the select reactor is filled with zeroes and as such a <code>NULL error_category</code> pointer. </p> <p> There is even more: <code>win_iocp_null_buffers_op</code> checks this in it's <code>on_completion()</code>: </p> <div class="wiki-code"><div class="code"><pre><span class="c1">// The reactor may have stored a result in the operation object.</span> <span class="k">if</span> <span class="p">(</span><span class="n">o</span><span class="o">-&gt;</span><span class="n">ec_</span><span class="p">)</span> <span class="n">ec</span> <span class="o">=</span> <span class="n">o</span><span class="o">-&gt;</span><span class="n">ec_</span><span class="p">;</span> </pre></div></div><p> This means if the reactor has saved a failure error_code in the operation it will use it instead of the one passed as an argument, BUT the operation does succeed in our case so it uses the <code>error_code</code> passed as an argument which has a <code>NULL error_category</code> pointer. </p> <p> And here is some additional info about the system I'm experiencing this on, maybe it's also dependent on this: Windows 7 SP1 x64 Built boost and the test code under MSVC 2010 at Debug|Win32 (32-bit build) </p> <p> Can you please look farther into this? </p> Ticket Segev Finer <segev208@…> Fri, 24 May 2013 08:58:09 GMT summary changed https://svn.boost.org/trac10/ticket/8613#comment:3 https://svn.boost.org/trac10/ticket/8613#comment:3 <ul> <li><strong>summary</strong> <span class="trac-field-old">[Windows] boost::asio::ip::tcp::socket::async_write() WriteHandler gets a boost::system::error_code with a NULL category pointer on success</span> → <span class="trac-field-new">[Windows] boost::asio::ip::tcp::socket::async_write(boost::asio::null_buffers(), ...) WriteHandler gets a boost::system::error_code with a NULL category pointer on success</span> </li> </ul> Ticket chris_kohlhoff Fri, 24 May 2013 09:28:20 GMT <link>https://svn.boost.org/trac10/ticket/8613#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8613#comment:4</guid> <description> <p> Thank you for taking the time to do a proper analysis. Can you please confirm whether the following diff corrects the issue for you: </p> <pre class="wiki">@ -235,8 +235,7 @@ void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op) op-&gt;ready_ = 1; // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, - 0, overlapped_contains_result, op)) + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op)) { // Out of resources. Put on completed queue instead. mutex::scoped_lock lock(dispatch_mutex_); @@ -256,8 +255,7 @@ void win_iocp_io_service::post_deferred_completions( op-&gt;ready_ = 1; // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, - 0, overlapped_contains_result, op)) + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op)) { // Out of resources. Put on completed queue instead. mutex::scoped_lock lock(dispatch_mutex_); @@ -284,8 +282,7 @@ void win_iocp_io_service::on_pending(win_iocp_operation* op) if (::InterlockedCompareExchange(&amp;op-&gt;ready_, 1, 0) == 1) { // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, - 0, overlapped_contains_result, op)) + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op)) { // Out of resources. Put on completed queue instead. mutex::scoped_lock lock(dispatch_mutex_); </pre> </description> <category>Ticket</category> </item> <item> <author>Segev Finer <segev208@…></author> <pubDate>Fri, 24 May 2013 11:00:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8613#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8613#comment:5</guid> <description> <p> The fix you posted does seem to work. </p> <p> Altough I think it's possible that this issue exists in the first place, since some other part of the code depended on <code>overlapped_contains_result</code> being passed and as such any code that uses this functions should be reviewed if it requires it or not. a quick search revelead that there aren't that many (Well at least ones that are actually relevant to win_iocp) </p> <p> For example: <code>win_iocp_overlapped_ptr::release()</code> calls <code>on_pending()</code>, and maybe it needs <code>overlapped_contains_result</code> and maybe it doesn't, I can't really tell from just reading the code. But maybe you already did this?... </p> <p> Setting the correct argument there is the best fix for this, anyhow IMHO. </p> <p> Thanks. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Sat, 25 May 2013 11:52:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8613#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8613#comment:6</guid> <description> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/84487" title="Fix bug on Windows where certain operations might generate an ...">[84487]</a>) Fix bug on Windows where certain operations might generate an error_code with an invalid (i.e. NULL) error_category. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8613" title="#8613: Bugs: [Windows] ... (closed: fixed)">#8613</a> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Mon, 27 May 2013 12:36:47 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/8613#comment:7 https://svn.boost.org/trac10/ticket/8613#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/84530" title="Merge from trunk. Fixes #8421, #8602, #7739, #8613, #7939. ...">[84530]</a>) Merge from trunk. Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8421" title="#8421: Bugs: docs show wrong overload (closed: fixed)">#8421</a>, <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8602" title="#8602: Bugs: Documentation references nonexistent boost::asio::waitable_timer (closed: fixed)">#8602</a>, <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7739" title="#7739: Bugs: Divide by zero error in hash_map.hpp (closed: fixed)">#7739</a>, <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8613" title="#8613: Bugs: [Windows] ... (closed: fixed)">#8613</a>, <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7939" title="#7939: Patches: remove warning/error in asio/impl/src.cpp (closed: fixed)">#7939</a>. </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84482" title="Fix potential deadlock in signal_set implementation.">r84482</a> | chris_kohlhoff | 2013-05-25 21:35:10 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Fix potential deadlock in signal_set implementation. </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84483" title="Fix error in acceptor example. Refs #8421">r84483</a> | chris_kohlhoff | 2013-05-25 21:38:01 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Fix error in acceptor example. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8421" title="#8421: Bugs: docs show wrong overload (closed: fixed)">#8421</a> </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84484" title="Fix waitable timer documentation. Refs #8602">r84484</a> | chris_kohlhoff | 2013-05-25 21:41:19 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Fix waitable timer documentation. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8602" title="#8602: Bugs: Documentation references nonexistent boost::asio::waitable_timer (closed: fixed)">#8602</a> </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84485" title="Add assertions that num_buckets_ is non-zero. Refs #7739">r84485</a> | chris_kohlhoff | 2013-05-25 21:46:20 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Add assertions that num_buckets_ is non-zero. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7739" title="#7739: Bugs: Divide by zero error in hash_map.hpp (closed: fixed)">#7739</a> </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84486" title="Automatically disable SSL compression. To mitigate the risk of ...">r84486</a> | chris_kohlhoff | 2013-05-25 21:50:52 +1000 (Sat, 25 May 2013) | 8 lines </p> <p> Automatically disable SSL compression. </p> <p> To mitigate the risk of certain attacks, SSL compression is now disabled by default. To enable, you can use the new ssl::context::clear_options() function like so: </p> <blockquote> <p> my_context.clear_options(asio::ssl::context::no_compression); </p> </blockquote> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84487" title="Fix bug on Windows where certain operations might generate an ...">r84487</a> | chris_kohlhoff | 2013-05-25 21:52:54 +1000 (Sat, 25 May 2013) | 3 lines </p> <p> Fix bug on Windows where certain operations might generate an error_code with an invalid (i.e. NULL) error_category. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/8613" title="#8613: Bugs: [Windows] ... (closed: fixed)">#8613</a> </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84488" title="Fix problem in #warning directive. Refs #7939">r84488</a> | chris_kohlhoff | 2013-05-25 21:57:36 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Fix problem in #warning directive. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7939" title="#7939: Patches: remove warning/error in asio/impl/src.cpp (closed: fixed)">#7939</a> </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84492" title="Fix potential data race due to reading the reactor pointer outside the ...">r84492</a> | chris_kohlhoff | 2013-05-25 22:35:43 +1000 (Sat, 25 May 2013) | 2 lines </p> <p> Fix potential data race due to reading the reactor pointer outside the lock. </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84494" title="Regenerate documentation.">r84494</a> | chris_kohlhoff | 2013-05-25 23:03:48 +1000 (Sat, 25 May 2013) | 1 line </p> <p> Regenerate documentation. </p> <hr /> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/84529" title="Add documentation for new features.">r84529</a> | chris_kohlhoff | 2013-05-27 22:17:19 +1000 (Mon, 27 May 2013) | 1 line </p> <p> Add documentation for new features. </p> <hr /> Ticket