Boost C++ Libraries: Ticket #7669: thread_group::join_all() should catch resource_deadlock_would_occur https://svn.boost.org/trac10/ticket/7669 <p> If a thread in thread_group is this_thread, join_all() throws resource_deadlock_would_occur. This violates the function post-condition: "Every thread in the group has terminated." Because of the above, and because it's impossible to enumerate the threads is a thread_group, it should catch resource_deadlock_would_occur and proceed with the joining loop. (The exception can be re-thrown when the loop ends.) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7669 Trac 1.4.3 viboes Fri, 09 Nov 2012 11:38:19 GMT <link>https://svn.boost.org/trac10/ticket/7669#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:1</guid> <description> <p> I think that we should change the pre-conditions of thread_group::join_all as the join() precondition should not be forcedly checked. </p> <pre class="wiki">Requires: for each thread th in the thread group satisfy this_thread::get_id()!=th.get_id(). </pre> </description> <category>Ticket</category> </item> <item> <author>Igor R. <boost.lists@…></author> <pubDate>Fri, 09 Nov 2012 11:55:43 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7669#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:2</guid> <description> <p> This would make thread_group unusable in the cases where the above precondition cannot be enforced. The question is why it's better than my proposal. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 09 Nov 2012 20:22:32 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7669#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/7669#comment:2" title="Comment 2">Igor R. &lt;boost.lists@…&gt;</a>: </p> <blockquote class="citation"> <p> This would make thread_group unusable in the cases where the above precondition cannot be enforced. The question is why it's better than my proposal. </p> </blockquote> <p> You are right, the user can not check this pre-condition as it has no access to the threads in the group other than duplicating. But calling to join_all and joining all but one of the threads don't respect either the post-conditions. I don't think it is a good design to to request to join on itself. </p> <p> I planned to deprecate thread_group so I don't want to invest too much on it. </p> <p> I guess there are two options: </p> <ul><li>the implementation check always if the this_thread is in the thread group and throw a specific exception, or </li><li>the library provides a function that states if this_thread is in the thread group, so that the user that is in a context that the current thread could be one of the group could check it. The join_all function has the Require clause described above. </li></ul><p> What do you think? What do you think? </p> </description> <category>Ticket</category> </item> <item> <author>Igor R. <boost.lists@…></author> <pubDate>Sat, 10 Nov 2012 19:19:14 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7669#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:4</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/7669#comment:3" title="Comment 3">viboes</a>: </p> <p> First of all, the question is whether we want to improve thread_group and make it more usable - or not. If you really intend to deprecate it, then perhaps changing the formal pre-condition is enough. On the other hand, if the intent is to improve the usability, I'am afraid none of the 2 options would really help. </p> <blockquote class="citation"> <p> You are right, the user can not check this pre-condition as it has no access to the threads in the group other than duplicating. But calling to join_all and joining all but one of the threads don't respect either the post-conditions. </p> </blockquote> <p> Right, the post-condition should be updated, if you decide to handle this_thread case. But please note that thread::join() post-condition is also incorrect with regard to this issue. IIUC, this story began when thread::join() just deadlocked if it was this_thread, and thread &amp; thread_group behaved consistently at this point; then the deadlock issue was solved by throwing resource_deadlock_would_occur exception, but neither formal post-condition of thread::join() nor thread_group behavior were updated. </p> <blockquote class="citation"> <p> I don't think it is a good design to to request to join on itself. </p> </blockquote> <p> Usually it's not a deliberate decision to join on itself, but design constraints, when trying to avoid this situation might unnecessarily complicate design. But "bad design" argument is even more applicable to thread::join() itself - nevertheless its behavior is reasonable and doesn't produce UB. </p> <blockquote class="citation"> <ul><li>the implementation check always if the this_thread is in the thread group and throw a specific exception </li></ul></blockquote> <p> What should the user do at this point? IIUC, it's impossible to recover from this situation (as opposed to thread::join() case!). </p> <blockquote class="citation"> <ul><li>the library provides a function that states if this_thread is in the thread group, so that the user that is in a context that the current thread could be one of the group could check it. The join_all function has the Require clause described above. </li></ul></blockquote> <p> Actually, this's equivalent to the above option, i.e the user will get information but won't be able to recover. </p> <p> P.S. please note that this ticket doesn't differ much from <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7668" title="#7668: Bugs: thread_group::join_all() should check whether its threads are joinable (closed: fixed)">#7668</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sat, 10 Nov 2012 21:04:38 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7669#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/7669#comment:4" title="Comment 4">Igor R. &lt;boost.lists@…&gt;</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/7669#comment:3" title="Comment 3">viboes</a>: </p> <p> First of all, the question is whether we want to improve thread_group and make it more usable - or not. If you really intend to deprecate it, then perhaps changing the formal pre-condition is enough. </p> </blockquote> <p> Ye sthis is my intention, but I need movable containers more portables. There are yet some compilers in the regression tests that don't support Boost.Move,/Container, ... </p> <blockquote class="citation"> <p> On the other hand, if the intent is to improve the usability, I'am afraid none of the 2 options would really help. </p> <blockquote class="citation"> <p> You are right, the user can not check this pre-condition as it has no access to the threads in the group other than duplicating. But calling to join_all and joining all but one of the threads don't respect either the post-conditions. </p> </blockquote> <p> Right, the post-condition should be updated, if you decide to handle this_thread case. But please note that thread::join() post-condition is also incorrect with regard to this issue. </p> </blockquote> <p> Please, could you say explicitly what is incorrect? </p> <blockquote class="citation"> <p> IIUC, this story began when thread::join() just deadlocked if it was this_thread, and thread &amp; thread_group behaved consistently at this point; then the deadlock issue was solved by throwing resource_deadlock_would_occur exception, but neither formal post-condition of thread::join() nor thread_group behavior were updated. </p> </blockquote> <p> You know more than me. </p> <blockquote class="citation"> <blockquote class="citation"> <p> I don't think it is a good design to to request to join on itself. </p> </blockquote> <p> Usually it's not a deliberate decision to join on itself, but design constraints, when trying to avoid this situation might unnecessarily complicate design. But "bad design" argument is even more applicable to thread::join() itself - nevertheless its behavior is reasonable and doesn't produce UB. </p> </blockquote> <p> Could you give an example where the user could want to call join_all from a thread inside the thread_group. I don't see none. In addition, it is difficult to provide a consistent behavior if this case could be a valid one. </p> <blockquote class="citation"> <blockquote class="citation"> <ul><li>the implementation check always if the this_thread is in the thread group and throw a specific exception </li></ul></blockquote> <p> What should the user do at this point? IIUC, it's impossible to recover from this situation (as opposed to thread::join() case!). </p> </blockquote> <p> You are right. this is not a solution. </p> <blockquote class="citation"> <blockquote class="citation"> <ul><li>the library provides a function that states if this_thread is in the thread group, so that the user that is in a context that the current thread could be one of the group could check it. The join_all function has the Require clause described above. </li></ul></blockquote> <p> Actually, this's equivalent to the above option, i.e the user will get information but won't be able to recover. </p> </blockquote> <p> Not really. Note that this is an exception throw to signal a pre-condition not satisfied situation? The user needs of course change his design. </p> <blockquote class="citation"> <p> P.S. please note that this ticket doesn't differ much from <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7668" title="#7668: Bugs: thread_group::join_all() should check whether its threads are joinable (closed: fixed)">#7668</a>. </p> </blockquote> <p> Yes, and join() has as pre-condition that a thread can not join itself. I was just extrapolating the same argument on the second solution I gave. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 11 Nov 2012 00:57:59 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/7669#comment:6 https://svn.boost.org/trac10/ticket/7669#comment:6 <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> <p> Committed in trunk revision <a class="changeset" href="https://svn.boost.org/trac10/changeset/81289" title="Thread: ref #7669">[81289]</a>. </p> Ticket anonymous Sun, 11 Nov 2012 19:04:17 GMT <link>https://svn.boost.org/trac10/ticket/7669#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:7</guid> <description> <p> Well my code did work in 1.51 but now it SIGABRTS because of this. How do I fix it now, before 1.53? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sat, 17 Nov 2012 12:59:41 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7669#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7669#comment:8</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/7669#comment:7" title="Comment 7">anonymous</a>: </p> <blockquote class="citation"> <p> Well my code did work in 1.51 but now it SIGABRTS because of this. How do I fix it now, before 1.53? </p> </blockquote> <p> Please, could you post the code that SIGABORTS? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 02 Dec 2012 10:47:26 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/7669#comment:9 https://svn.boost.org/trac10/ticket/7669#comment:9 <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">fixed</span> </li> </ul> <p> Committed revision <a class="changeset" href="https://svn.boost.org/trac10/changeset/81667" title="Thread: merge from trunk 1.53">[81667]</a>. </p> Ticket