[Twisted-Python] Forking after starting AsyncioSelectorReactor: Supported?
![](https://secure.gravatar.com/avatar/c278b7144feb496c731ee0514355548c.jpg?s=120&d=mm&r=g)
Hi Twisted list! I have a library that is attempting to start an AsyncioSelectorReactor, fork the process, and then open a network socket on macOS. When the network socket is opened, Twisted throws an [Errno 9] "Bad file descriptor" exception at me. I get no such exception on Ubuntu. If I change the sequence from: setup_reactor('AsyncioSelectorReactor') fork_and_continue_in_child() run_server() to: fork_and_continue_in_child() # fork first setup_reactor('AsyncioSelectorReactor') run_server() Then everything works okay. Also if I use SelectReactor rather than AsyncioSelectorReactor then it doesn't matter which order I fork in. So my question is, does Twisted support being forked after starting a reactor or not? -- David Foster | Seattle, WA, USA P.S. For more details see this Django Channels thread: https://github.com/django/channels/issues/962#issuecomment-414103367
![](https://secure.gravatar.com/avatar/152986af8e990c9c8b61115f298b9cb2.jpg?s=120&d=mm&r=g)
On Mon, Aug 27, 2018 at 09:12:57PM -0700, David Foster wrote:
So my question is, does Twisted support being forked after starting a reactor or not?
I haven't used Twisted with the AsyncioSelectorReactor on macOS myself, but the `asyncio` docs suggest[1] that the default macOS event loop uses the `kqueue` system call. Searching for "macos fork kqueue" finds a report[2] of the same behaviour in the C++ Boost asyncio library. Apple doesn't seem to publish manpages publically anymore, but the `kqueue` system call was borrowed from FreeBSD which does[3]: # The kqueue() system call creates a new kernel event queue and returns a # descriptor. The queue is not inherited by a child created with fork(2). So, my guess is that `kqueue` just can't be used with `fork` in that way. If you really need to set up a reactor and then fork, perhaps you can configure `asyncio` to use the `selectors.SelectSelector` or `selectors.PollSelector` event loops instead; they're less efficient, but they should work after a fork. This behaviour doesn't occur on Ubuntu because Linux provides the `epoll` system call instead of `kqueue`, which behaves differently. [1]: https://docs.python.org/3.6/library/asyncio-eventloops.html#mac-os-x [2]: https://svn.boost.org/trac10/ticket/3238 [3]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&manpath=FreeBSD+11.2-RELEASE+and+Ports
![](https://secure.gravatar.com/avatar/c278b7144feb496c731ee0514355548c.jpg?s=120&d=mm&r=g)
Thank you for the detailed research Tim. Indeed it seems we’ll have to either change the order of {start reactor, fork} or use a different reactor type, since this problem seems likely to remain so long as asyncio uses the kqueue primitive on macOS, which seems unlikely to change. - David
![](https://secure.gravatar.com/avatar/152986af8e990c9c8b61115f298b9cb2.jpg?s=120&d=mm&r=g)
On Mon, Aug 27, 2018 at 09:12:57PM -0700, David Foster wrote:
So my question is, does Twisted support being forked after starting a reactor or not?
I haven't used Twisted with the AsyncioSelectorReactor on macOS myself, but the `asyncio` docs suggest[1] that the default macOS event loop uses the `kqueue` system call. Searching for "macos fork kqueue" finds a report[2] of the same behaviour in the C++ Boost asyncio library. Apple doesn't seem to publish manpages publically anymore, but the `kqueue` system call was borrowed from FreeBSD which does[3]: # The kqueue() system call creates a new kernel event queue and returns a # descriptor. The queue is not inherited by a child created with fork(2). So, my guess is that `kqueue` just can't be used with `fork` in that way. If you really need to set up a reactor and then fork, perhaps you can configure `asyncio` to use the `selectors.SelectSelector` or `selectors.PollSelector` event loops instead; they're less efficient, but they should work after a fork. This behaviour doesn't occur on Ubuntu because Linux provides the `epoll` system call instead of `kqueue`, which behaves differently. [1]: https://docs.python.org/3.6/library/asyncio-eventloops.html#mac-os-x [2]: https://svn.boost.org/trac10/ticket/3238 [3]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&manpath=FreeBSD+11.2-RELEASE+and+Ports
![](https://secure.gravatar.com/avatar/c278b7144feb496c731ee0514355548c.jpg?s=120&d=mm&r=g)
Thank you for the detailed research Tim. Indeed it seems we’ll have to either change the order of {start reactor, fork} or use a different reactor type, since this problem seems likely to remain so long as asyncio uses the kqueue primitive on macOS, which seems unlikely to change. - David
participants (2)
-
David Foster
-
Tim Allen