Комментарии 12
Ещё один любопытный вопрос - что из себя будет представлять порождённый процесс: обычный линейный код? А если он тоже захочет работать в event loop?
0
Порожденный процесс представляет собой полную копию своего родителя. В случае event loop лучше использовать потоки, если конечно модель позволяет :))
0
perl не позволяет, к сожалению. Я тестирую производительность нитей каждые несколько версий perl, и в последний раз она всё ещё находилась ниже плинтуса.
0
Так в перле и event loop полноценного нет (если имеется ввиду aio, iocp, kqueue, kevent), разве только poll/select, но это очень медленно.
А использовать имеет смысл, если SMP.
Обработки форк и не должно быть. Процессы нужно форкать _до_.
А использовать имеет смысл, если SMP.
Обработки форк и не должно быть. Процессы нужно форкать _до_.
0
Event loop - есть. Вполне полноценные. Моя реализация использует epoll, а CPAN-модуль Event::Lib использует libevent (т.е. тот же epoll под линухом, kqueue под *BSD, и другие методы в других системах).
SMP здесь не при чём, Вы, вероятно, не поняли суть вопроса. Запускать какие-то задачи в отдельных процессах смысл есть не зависимо от наличия SMP. Вопрос в том, есть ли смысл запускать их через fork, без exec?
Форкать _до_ далеко не всегда возможно, задачи требующие обработки в отдельном процессе могут возникать в процессе получения каких-то событий, на все случаи жизни тут заранее ненафоркаешься.
SMP здесь не при чём, Вы, вероятно, не поняли суть вопроса. Запускать какие-то задачи в отдельных процессах смысл есть не зависимо от наличия SMP. Вопрос в том, есть ли смысл запускать их через fork, без exec?
Форкать _до_ далеко не всегда возможно, задачи требующие обработки в отдельном процессе могут возникать в процессе получения каких-то событий, на все случаи жизни тут заранее ненафоркаешься.
0
Вроде грабли с fork связаны с особенностями epoll в linux - наследованием дескрипторов
0
Это частный случай. Посмотрите на ситуацию более широко: есть процесс, в котором настроены какие-то таймеры, сигналы, есть даже очередь ещё не обработанных пользовательских событий (ну, типа одна часть кода другой сообщение послала) - это помимо событий I/O. И вот fork этот процесс дублирует, и таких процессов становится два.
Если второй процесс просто будет 20 минут обсчитывать пачку данных, сохранит результат на винт и выйдет - один разговор. В этом случае, действительно, большинство побочных эффектов будет связано с особенностями реализации epoll и FD. Но что если второму процессу нужно делать что-то более сложное, и он тоже хочет использовать event loop? А у него в памяти осталась куча настроенных событий от родительского процесса...
Вообще, идея сдублировать процесс в котором настроена куча событий и продолжить выполнять оба таких процесса одновременно воспринимается достаточно дико.
Если второй процесс просто будет 20 минут обсчитывать пачку данных, сохранит результат на винт и выйдет - один разговор. В этом случае, действительно, большинство побочных эффектов будет связано с особенностями реализации epoll и FD. Но что если второму процессу нужно делать что-то более сложное, и он тоже хочет использовать event loop? А у него в памяти осталась куча настроенных событий от родительского процесса...
Вообще, идея сдублировать процесс в котором настроена куча событий и продолжить выполнять оба таких процесса одновременно воспринимается достаточно дико.
0
Если честно, не очень понял суть проблемы. Как то сумбурно все понял. То ли примеров не хватает из жизни, то ли тормоз.
А как в вашем понимании эта проблема должна быть решена? Как эта же технология евент-лупов реализована в других языках/системах?
А как в вашем понимании эта проблема должна быть решена? Как эта же технология евент-лупов реализована в других языках/системах?
0
А вот так и реализована — без обращения внимания на проблему fork. В частности, под виндой, насколько я слышал, fork нет вообще; а нет fork - нет проблемы.
Похоже, эту проблему автоматически решить нельзя. Только ручками: в каждом приложении используещем event loop внимательно следить за всеми fork-ами (в т.ч. и находящимся внутри используемых этим приложением чужих библиотек!), думать какие проблемы эти fork-и вызовут и как их обойти. Посколько гимор всё это просто дикий, то рекомендуется одновременно event loop и fork не использовать. Либо на-fork-ать нужные процессы до входа в event loop, либо вместо fork использовать fork+exec (и закрывать все fd) создавая новый процесс никак не могущий нарушить работу event loop в основном процессе.
Похоже, эту проблему автоматически решить нельзя. Только ручками: в каждом приложении используещем event loop внимательно следить за всеми fork-ами (в т.ч. и находящимся внутри используемых этим приложением чужих библиотек!), думать какие проблемы эти fork-и вызовут и как их обойти. Посколько гимор всё это просто дикий, то рекомендуется одновременно event loop и fork не использовать. Либо на-fork-ать нужные процессы до входа в event loop, либо вместо fork использовать fork+exec (и закрывать все fd) создавая новый процесс никак не могущий нарушить работу event loop в основном процессе.
0
В другом вашем посте вы упоминули, что библиотека libev решает или по крайней мере пытается решать эту проблему функциями ev_default_fork, ev_loop_fork. Насколько я понял из документации, эти функции выполняют переинициализацию используемого объекта (например epoll) на уровне ядра, после чего потомок может использовать функции библиотеки. Вот только что скрывается за этой "переинициализацией"?
0
Помимо epoll хватает и других событий — таймеры, пользовательские, сигналы, etc. Всё это добро автоматически переинициализировать невозможно — ведь если делается fork без exec в процессе работы event loop, то предполагается что оба процесса продолжат работать в event loop... так что просто автоматически при fork почистить все обработчики событий в child как-то не правильно и не логично.
Насколько я понял, libev решает эту проблему не какой-то магической переинициализацией epoll_fd, а предоставляя возможность пользователю установить свой обработчик fork — который будет вызван при fork и позволит юзеру самому разрулить, какие обработчики событий оставить в child, а какие в parent. Это достаточно сложная задача, т.к. зачастую для этого нужно знать текущее состояние приложения, а оно в event-loop based приложениях зависит от слишком многих факторов. Впрочем, понятно, что в разных процессах должен быть разный epoll_fd, так что libev действительно может создавать новый epoll_fd автоматически в child процессе — но это не сильно облегчает жизнь программисту и основная сложность всё равно ложится на его обработчик события "fork".
Насколько я понял, libev решает эту проблему не какой-то магической переинициализацией epoll_fd, а предоставляя возможность пользователю установить свой обработчик fork — который будет вызван при fork и позволит юзеру самому разрулить, какие обработчики событий оставить в child, а какие в parent. Это достаточно сложная задача, т.к. зачастую для этого нужно знать текущее состояние приложения, а оно в event-loop based приложениях зависит от слишком многих факторов. Впрочем, понятно, что в разных процессах должен быть разный epoll_fd, так что libev действительно может создавать новый epoll_fd автоматически в child процессе — но это не сильно облегчает жизнь программисту и основная сложность всё равно ложится на его обработчик события "fork".
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Fork в приложениях использующих event loop