Boost C++ Libraries: Ticket #5752: boost::call_once() is unreliable on some platforms https://svn.boost.org/trac10/ticket/5752 <p> boost::call_once() is an implementation of Mike Burrows's fast_pthread_once() algorithm, as described in <a class="ext-link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm"><span class="icon">​</span>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm</a>. In the correctness proof, there is a requirement that loads and stores of the epoch value are atomic (i.e., do not exhibit word tearing). In Mike's example implementation, the sig_atomic_t type is used, which is required by the C standard to support atomic loads and stores. </p> <p> However, in the boost::call_once() implementation, the epoch value is defined as uintmax_t, which has no such guarantee, and in practice is not atomic on some architectures. E.g., on OpenBSD/i386, uintmax_t is a 64-bit type and assignments to a 64-bit memory address must be split into two (non-atomic) store instructions. </p> <p> Therefore, thread/pthread/once.hpp should be changed to use a type that is guaranteed to support atomic loads and stores instead of uintmax_t. Additionally, since once_flag::epoch is accessed by multiple threads without any synchronization, it should be marked volatile. </p> <p> (Alternatively, the new C++0x atomic operations library appears suitable for this use as well.) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/5752 Trac 1.4.3 viboes Sun, 04 Dec 2011 01:08:59 GMT component changed; cc set https://svn.boost.org/trac10/ticket/5752#comment:1 https://svn.boost.org/trac10/ticket/5752#comment:1 <ul> <li><strong>cc</strong> <span class="trac-author">viboes</span> added </li> <li><strong>component</strong> <span class="trac-field-old">threads</span> → <span class="trac-field-new">thread</span> </li> </ul> Ticket viboes Sun, 11 Dec 2011 15:18:53 GMT keywords set https://svn.boost.org/trac10/ticket/5752#comment:2 https://svn.boost.org/trac10/ticket/5752#comment:2 <ul> <li><strong>keywords</strong> once added </li> </ul> Ticket viboes Sat, 14 Jul 2012 19:15:36 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:3</guid> <description> <p> I would like to make it more reliable, but I don't know on which platforms uintmax_t is unreliable and which type will be reliable for these platforms. Is sig_atomic_t available and reliable on these platforms? Could some one help on this? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 12 Aug 2012 19:35:39 GMT</pubDate> <title>owner, status changed https://svn.boost.org/trac10/ticket/5752#comment:4 https://svn.boost.org/trac10/ticket/5752#comment:4 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Anthony Williams</span> to <span class="trac-author">viboes</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket viboes Sat, 18 Aug 2012 14:36:57 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:5</guid> <description> <p> Does sig_atomic_t works for you? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sat, 18 Aug 2012 14:43:37 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/5752#comment:6 https://svn.boost.org/trac10/ticket/5752#comment:6 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.52.0</span> </li> </ul> <p> Committed in trunk revision <a class="changeset" href="https://svn.boost.org/trac10/changeset/80078" title="Thread: try to fix 5752">[80078]</a>. </p> Ticket viboes Sun, 19 Aug 2012 15:48:28 GMT milestone changed https://svn.boost.org/trac10/ticket/5752#comment:7 https://svn.boost.org/trac10/ticket/5752#comment:7 <ul> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.52.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> <p> Committed in trunk revision <a class="changeset" href="https://svn.boost.org/trac10/changeset/80082" title="Thread: It seems that the csignal inclusion is failing in all testers, ...">[80082]</a>. </p> Ticket viboes Tue, 21 Aug 2012 05:17:15 GMT milestone changed https://svn.boost.org/trac10/ticket/5752#comment:8 https://svn.boost.org/trac10/ticket/5752#comment:8 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.52.0</span> </li> </ul> Ticket fhess Mon, 03 Sep 2012 14:03:01 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:9</guid> <description> <p> When SIG_ATOMIC_MAX is defined (that is, when I compile on Linux with g++ 4.4.5 and -std=c++0x) call_once does not work. It never calls my function at all. I debugged it, it happens because in thread/pthread/once.hpp in the call_once method it compares epoch and this_thread_epoch. epoch is set to 0 and this_thread_epoch is set to -1 so the comparison is false and call once does nothing. It seems the problem is due to uintmax_atomic_t being defined as a sig_atomic_t which turns out to be a signed rather than unsigned type. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>fhess</dc:creator> <pubDate>Mon, 03 Sep 2012 14:55:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5752#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:10</guid> <description> <p> Some more info, it seems the problem is due to SIG_ATOMIC_MAX being defined in my code when I include once.hpp, but it is not defined in once.cpp when the libboost_thread is compiled. By default, cstdint doesn't define SIG_ATOMIC_MAX when compiling in c++ mode, unless you define <code>__STDC_LIMIT_MACROS</code> before stdint.h is included. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Frank Mori Hess</dc:creator> <pubDate>Mon, 03 Sep 2012 15:10:01 GMT</pubDate> <title>cc changed https://svn.boost.org/trac10/ticket/5752#comment:11 https://svn.boost.org/trac10/ticket/5752#comment:11 <ul> <li><strong>cc</strong> <span class="trac-author">fmhess@…</span> added </li> </ul> Ticket viboes Sun, 09 Sep 2012 13:24:04 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:12</guid> <description> <p> I will add it </p> <pre class="wiki">Index: pthread/once.hpp =================================================================== --- pthread/once.hpp (revision 80450) +++ pthread/once.hpp (working copy) @@ -17,6 +17,8 @@ #include &lt;boost/thread/pthread/pthread_mutex_scoped_lock.hpp&gt; #include &lt;boost/cstdint.hpp&gt; #include &lt;boost/thread/detail/delete.hpp&gt; +// Force SIG_ATOMIC_MAX tobe defined +#define __STDC_LIMIT_MACROS #include &lt;csignal&gt; #include &lt;boost/config/abi_prefix.hpp&gt; </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 09 Sep 2012 14:48:39 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5752#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:13</guid> <description> <p> Committed in trunk revision 80466. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Frank Mori Hess</dc:creator> <pubDate>Sun, 09 Sep 2012 15:25:06 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5752#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:14</guid> <description> <p> SIG_ATOMIC_MAX actually gets defined by stdint.h/cstdint not csignal so it seems like your define should be earlier. Actually, even then there's still a problem since the user might include stdint.h before they include the once.hpp, without having <code>__STD_LIMIT_MACROS</code> defined. In that case, SIG_ATOMIC_MAX won't be defined in their code but it will be defined in the thread library, leading to incompatible types again. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Thu, 13 Sep 2012 19:17:15 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5752#comment:15 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:15</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5752#comment:14" title="Comment 14">fmhess</a>: </p> <blockquote class="citation"> <p> SIG_ATOMIC_MAX actually gets defined by stdint.h/cstdint not csignal so it seems like your define should be earlier. Actually, even then there's still a problem since the user might include stdint.h before they include the once.hpp, without having <code>__STD_LIMIT_MACROS</code> defined. In that case, SIG_ATOMIC_MAX won't be defined in their code but it will be defined in the thread library, leading to incompatible types again. </p> </blockquote> <p> It seems then that I can not relay on whether SIG_ATOMIC_MAX is defined or not, but I need a value to mean not-a-valid value. Have a suggestion? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Frank Mori Hess</dc:creator> <pubDate>Fri, 14 Sep 2012 00:45:02 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5752#comment:16 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:16</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5752#comment:15" title="Comment 15">viboes</a>: </p> <blockquote class="citation"> <p> It seems then that I can not relay on whether SIG_ATOMIC_MAX is defined or not, but I need a value to mean not-a-valid value. Have a suggestion? </p> </blockquote> <p> How about using a boost::atomic&lt;unsigned long&gt; for the epoch? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Mon, 17 Sep 2012 21:35:34 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/5752#comment:17 https://svn.boost.org/trac10/ticket/5752#comment:17 <ul> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.52.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5752#comment:16" title="Comment 16">fmhess</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5752#comment:15" title="Comment 15">viboes</a>: </p> <blockquote class="citation"> <p> It seems then that I can not relay on whether SIG_ATOMIC_MAX is defined or not, but I need a value to mean not-a-valid value. Have a suggestion? </p> </blockquote> <p> How about using a boost::atomic&lt;unsigned long&gt; for the epoch? </p> </blockquote> <p> I will try to use it when released. I can not depend on a non released library. </p> Ticket kab@… Thu, 11 Oct 2012 23:22:15 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:18 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:18</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5752#comment:9" title="Comment 9">fhess</a>: </p> <blockquote class="citation"> <p> When SIG_ATOMIC_MAX is defined ... call_once does not work. ... It seems the problem is due to uintmax_atomic_t being defined as a sig_atomic_t which turns out to be a signed rather than unsigned type. </p> </blockquote> <p> This problem with using sig_atomic_t has been reported separately: <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/7499"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/7499</a> Too bad I didn't know about this sooner. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrey Semashev</dc:creator> <pubDate>Sun, 13 Jan 2013 20:31:41 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/5752 https://svn.boost.org/trac10/ticket/5752 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">atomic_once.patch</span> </li> </ul> <p> The patch ports POSIX implementation of call_once to Boost.Atomic. </p> Ticket viboes Mon, 14 Jan 2013 23:31:26 GMT milestone changed https://svn.boost.org/trac10/ticket/5752#comment:19 https://svn.boost.org/trac10/ticket/5752#comment:19 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.53.0</span> </li> </ul> Ticket viboes Wed, 16 Jan 2013 21:53:09 GMT <link>https://svn.boost.org/trac10/ticket/5752#comment:20 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5752#comment:20</guid> <description> <p> Committed in trunk revision <a class="changeset" href="https://svn.boost.org/trac10/changeset/82513" title="Thread: Added atomic once implementation + variadi call_once for pthread">[82513]</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 27 Jan 2013 15:18:29 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/5752#comment:21 https://svn.boost.org/trac10/ticket/5752#comment:21 <ul> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.53.0</span> → <span class="trac-field-new">Boost 1.54.0</span> </li> </ul> Ticket viboes Sat, 16 Feb 2013 21:45:26 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/5752#comment:22 https://svn.boost.org/trac10/ticket/5752#comment:22 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> merged from trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/82838" title="Thread: merge from trunk 1.54 - once_atomic; null_mutex">[82838]</a> </p> Ticket