Boost C++ Libraries: Ticket #4162: io_service can't be used correctly after fork(). https://svn.boost.org/trac10/ticket/4162 <p> Hello, </p> <p> I'm trying to run standard "prefork" unix configuration with boost-asio. </p> <p> I have following setup: </p> <ol><li>I bind to some port. </li></ol><ol start="2"><li>I prefork several processes. </li></ol><ol start="3"><li>As new connection is avalible one of processes accept it </li></ol><p> and run the main loop. </p> <hr /> <p> Issue: </p> <p> The io_service is created at the begging and creates eventfd (or pipe), and unlike devpoll, kqueue or epoll it is shared between forked processes. </p> <hr /> <p> There is the problem: </p> <p> When one thread in process try to "post" something to event loop it interrupts the select with evenfd... And accidentially other process may actually receive this notification and wake up when the main process that should receive notification does not. </p> <hr /> <p> In short </p> <p> If io_service was created before fork(), post() member function would not work correctly. </p> <hr /> <p> Solutions: </p> <p> 1) Postpone creation of pipe/eventfd to the stage when run() is called instead of construction of io_service. 2) Reopen interrupter if fork() was called. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4162 Trac 1.4.3 artyomtnk@… Sat, 01 May 2010 20:32:24 GMT <link>https://svn.boost.org/trac10/ticket/4162#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:1</guid> <description> <p> Any chances to get it fixed? </p> <p> I'm developer of CppCMS framework. I use Boost.Asio as center event loop and support of prefork is one of central features of this framework. Now I'm quite stuck - I need either got this bug fixed, remove support of prefork or replace boost.asio with other library. </p> <p> Thanks, </p> <blockquote> <p> Artyom </p> </blockquote> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Sat, 01 May 2010 22:33:54 GMT</pubDate> <title>type, milestone changed https://svn.boost.org/trac10/ticket/4162#comment:2 https://svn.boost.org/trac10/ticket/4162#comment:2 <ul> <li><strong>type</strong> <span class="trac-field-old">Bugs</span> → <span class="trac-field-new">Feature Requests</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.43.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> <ol><li>Bind to port. </li><li>dup() acceptor descriptor. </li><li>Destroy io_service. </li><li>Prefork. </li><li>Create new io_service in child. </li><li>acceptor::assign() </li></ol> Ticket artyomtnk@… Sun, 02 May 2010 04:32:35 GMT <link>https://svn.boost.org/trac10/ticket/4162#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:3</guid> <description> <blockquote class="citation"> <ol><li>Bind to port. </li><li>dup() acceptor descriptor. </li><li>Destroy io_service. </li><li>Prefork. </li><li>Create new io_service in child. </li><li>acceptor::assign() </li></ol><p> </p> </blockquote> <p> This was the first thing I thought and tried. But, I allow the library user to start some asynchronous actions before fork() at all. For example: </p> <ul><li>I allow him to create timers </li><li>I allow hit to post() some handlers to event queue so once the service is started they would be dispatched. </li></ul><p> So the solution of creating new io_service is not quite fits my needs. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Sun, 02 May 2010 05:17:53 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4162#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:4</guid> <description> <p> Sorry, but for now you'll simply have to start those asynchronous actions after the fork. </p> </description> <category>Ticket</category> </item> <item> <author>sephirok@…</author> <pubDate>Mon, 06 Sep 2010 14:13:12 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4162#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:5</guid> <description> <p> It would be real nice to have boost.asio play nice with fork(), even after io_service creation or .run(). </p> </description> <category>Ticket</category> </item> <item> <author>artyomtnk@…</author> <pubDate>Mon, 06 Sep 2010 14:28:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4162#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:6</guid> <description> <p> To be honst, from my knowlege of boost.asio and my implementation of fork aware boost<strong>er</strong>.aio for CppCMS I don't think this is quite simple feature to implement, few points: </p> <ul><li>Reactor should be created, first time only after fork, probably on call of io_service::run, otherwise, its file descriptor (for epoll/depoll/kqueue) would be shared between processes., </li><li>Select interrupters should be created after fork as well as it my be shared between processes as well and lead to very bad bugs. </li></ul> </description> <category>Ticket</category> </item> <item> <author>sephirok@…</author> <pubDate>Mon, 06 Sep 2010 23:49:28 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4162#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:7</guid> <description> <p> I guess it wouldn't be possible to close the duplicate descriptors in the child and sort of "reinitialize" the io_service with a new eventfd aso. </p> <p> Also what I haven't gotten working yet is just forking, letting the parent die and continuing as child - asio seems to hiccup. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Wed, 02 Mar 2011 08:28:04 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4162#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4162#comment:8</guid> <description> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/69467" title="* Add support for the fork() system call. Programs that use fork must ...">[69467]</a>) * Add support for the fork() system call. Programs that use fork must call </p> <blockquote> <p> io_service.notify_fork() at the appropriate times. Two new examples have been added showing how to use this feature. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3238" title="#3238: Bugs: asio, kqueue_reactor, result of kevent() isn't checked for error (closed: fixed)">#3238</a>, <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4162" title="#4162: Feature Requests: io_service can't be used correctly after fork(). (closed: fixed)">#4162</a>. </p> </blockquote> <ul><li>Clean up the handling of errors reported by the close() system call. In particular, assume that most operating systems won't have close() fail with EWOULDBLOCK, but if it does then set blocking mode and restart the call. If any other error occurs we assume the descriptor is closed. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3307" title="#3307: Bugs: Stream descriptor blocking state set on close (closed: fixed)">#3307</a>. </li></ul><ul><li>EV_ONESHOT seems to cause problems on some versions of Mac OS X, with the io_service destructor getting stuck inside the close() system call. Use EV_CLEAR instead. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5021" title="#5021: Bugs: io_service destructor hangs on Mac OS X (closed: fixed)">#5021</a>. </li></ul><ul><li>Include function name in exception what() messages. </li></ul><ul><li>Fix insufficient initialisers warning with MinGW. </li></ul><ul><li>Make the shutdown_service() member functions private. </li></ul><ul><li>Add archetypes for testing socket option functions. </li></ul><ul><li>Add missing lock in signal_set_service::cancel(). </li></ul><ul><li>Fix copy/paste error in <a class="missing wiki">SignalHandler</a> example. </li></ul><ul><li>The signal header needs to be included in signal_set_service.hpp so that we can use constants like NSIG and SIGRTMAX. </li></ul><ul><li>Don't use Boost.Thread's convenience header. Use the header file that is specifically for the boost::thread class instead. </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>chris_kohlhoff</dc:creator> <pubDate>Mon, 06 Jun 2011 01:44:19 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4162#comment:9 https://svn.boost.org/trac10/ticket/4162#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> Applied to release branch in <a class="changeset" href="https://svn.boost.org/trac10/changeset/72428" title="Merge asio from trunk.">[72428]</a>. </p> Ticket