Opened 12 years ago
Closed 11 years ago
#4162 closed Feature Requests (fixed)
io_service can't be used correctly after fork().
Reported by: | Owned by: | chris_kohlhoff | |
---|---|---|---|
Milestone: | To Be Determined | Component: | asio |
Version: | Boost 1.42.0 | Severity: | Problem |
Keywords: | asio posix fork unix | Cc: |
Description
Hello,
I'm trying to run standard "prefork" unix configuration with boost-asio.
I have following setup:
- I bind to some port.
- I prefork several processes.
- As new connection is avalible one of processes accept it
and run the main loop.
Issue:
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.
There is the problem:
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.
In short
If io_service was created before fork(), post() member function would not work correctly.
Solutions:
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.
Change History (9)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
Milestone: | Boost 1.43.0 → To Be Determined |
---|---|
Type: | Bugs → Feature Requests |
- Bind to port.
- dup() acceptor descriptor.
- Destroy io_service.
- Prefork.
- Create new io_service in child.
- acceptor::assign()
comment:3 by , 12 years ago
- Bind to port.
- dup() acceptor descriptor.
- Destroy io_service.
- Prefork.
- Create new io_service in child.
- acceptor::assign()
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:
- I allow him to create timers
- I allow hit to post() some handlers to event queue so once the service is started they would be dispatched.
So the solution of creating new io_service is not quite fits my needs.
comment:4 by , 12 years ago
Sorry, but for now you'll simply have to start those asynchronous actions after the fork.
comment:5 by , 12 years ago
It would be real nice to have boost.asio play nice with fork(), even after io_service creation or .run().
comment:6 by , 12 years ago
To be honst, from my knowlege of boost.asio and my implementation of fork aware booster.aio for CppCMS I don't think this is quite simple feature to implement, few points:
- 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.,
- Select interrupters should be created after fork as well as it my be shared between processes as well and lead to very bad bugs.
comment:7 by , 12 years ago
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.
Also what I haven't gotten working yet is just forking, letting the parent die and continuing as child - asio seems to hiccup.
comment:8 by , 12 years ago
(In [69467]) * Add support for the fork() system call. Programs that use fork must call
io_service.notify_fork() at the appropriate times. Two new examples have been added showing how to use this feature. Refs #3238, #4162.
- 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 #3307.
- 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 #5021.
- Include function name in exception what() messages.
- Fix insufficient initialisers warning with MinGW.
- Make the shutdown_service() member functions private.
- Add archetypes for testing socket option functions.
- Add missing lock in signal_set_service::cancel().
- Fix copy/paste error in SignalHandler example.
- The signal header needs to be included in signal_set_service.hpp so that we can use constants like NSIG and SIGRTMAX.
- Don't use Boost.Thread's convenience header. Use the header file that is specifically for the boost::thread class instead.
comment:9 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Applied to release branch in [72428].
Any chances to get it fixed?
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.
Thanks,