Вызвать system() внутри разветвленного (дочернего) процесса, когда у родительского процесса много потоков, сокетов и IPC

У меня есть программа, которая имеет много тем. Некоторые потоки являются TCP-серверами... Каждый сервер запускает новые потоки для обработки любых новых соединений.

Внутри одного из потоков, который обрабатывает один клиент, я вызываю fork(). Дочерний процесс вызывает setpgid () (для создания новой группы), а затем system () (функция стандартной библиотеки C/C++). Родительский процесс продолжает дремать (функция usleep ()) и проверяет ограничение по времени. Если ограничение по времени превышено до того, как дочерний процесс возвращается из system (), родительский SIGKILLs дочерний.

Я использую: Linux (Ubuntu), pthreads и т. Д. Ничего, кроме стандартной библиотеки C/C++!

Мои вопросы: что происходит со всеми потоками и сокетами TCP на дочернем процессе? Унаследованы ли эти вещи от родительского процесса? Будут ли и дочерний, и родительский запускать все эти потоки и TCP-серверы одновременно? Это не имеет смысла для меня... А когда родительский SIGKILLs дочерний, сокеты будут закрыты только внутри дочернего элемента или также в родительском?

В настоящее время я на самом деле использую exec() для очистки всего изображения дочернего процесса, но я бы предпочел вызвать system () напрямую, если это безопасно.

1 ответ

Решение

Файловые дескрипторы (также известные как fds), такие как сокеты TCP, наследуются через форк. Файл или устройство, находящиеся "за ними", обычно остаются открытыми и работоспособными до тех пор, пока последний дескриптор файла не будет закрыт или закрыт при завершении процесса. Таким образом, SIGKILL'ing дочерний элемент не повлияет на сокеты TCP, используемые совместно с родителем.

Однако только дочерний поток fork() выполняется в дочернем процессоре. Другие потоки управления не копируются. Ваша ситуация выглядит примерно так:

+-- PID 100 -------------+ # parent
| fds: 0, 1, 2, 3 ... N  | # fds: stdin, stdout, stderr, socket ... socket
| threads:               |
|      0 (main)          |
|      1 (tcp server)    |
|      2 (forky)  ---------(fork(2))-+
|      ...               |           |
|      N (tcp server)    |           |
+------------------------+           |
                                     |
                                     |
                     +-- PID 101 -------------+ # child
                     | fds: 0, 1, 2, 3 ... N  | # fds: inherited
                     | threads:               |
                     |      0 (copy of forky) | # will exec() ?
                     +------------------------+

призвание exec заменит изображение процесса PID 101 текстом main() (и закройте все файловые дескрипторы, помеченные как FD_CLOEXEC). призвание system("whatever")напротив, вероятно, породил бы по крайней мере еще два процесса: (великий) ребенок /bin/sh и (великий) внук "что угодно".

Очень легко смешивать себя, смешивая потоки, вилки и общие ресурсы, особенно если старые, старые интерфейсы, такие как system() брошены в смесь. Идите медленно, явно отбрасывайте ресурсы, которые вам не нужны, когда они вам не нужны, и устраняйте неисправности по одной вещи за раз.

Другие вопросы по тегам