Форум сайта python.su
У меня есть интересный вопрос… Привет всем!
Есть такой кусочек кода:
pid = os.fork()
if pid > 0:
sys.exit(0)
sys.stdout.flush()
sys.stderr.flush()
si = open('/dev/null', 'r')
so = open('/dev/null', 'a+')
se = open('/dev/null', 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
Офлайн
Форкаются через dup, как и файлы.
Т.е. с самим сокетом проблемы нет.
Беда может прийти, если родитель и потомок пытаются выполнить запрос к БД без взаимной синхронизации. Сервер может не понять, если ему в один сокет будут
пихать одновременно два запроса. А еще у клиента базы данных есть свой state - PGconn из libpq.
При обработке запроса pg_conn изменяется. Это - локальная память процесса, синхронизации я не увидел. Т.е. выбирая, например, результаты запроса в родителе библиотека никак не сигналит об этом потомку. А pg_conn имеет внутренний буфер - примерно как FILE* является надстройкой над int file descriptor.
В итоге - порвется все к чертям.
Офлайн
Хм… Спасибо, ясно.
Офлайн
Нет. Стоп. Чего-то я запутался.
В моём примере у нас умирает родитель, в котором отрабатывается gc, который закрывает (в теории) соединение. По идее клиент должен послать серверу сообщение о том, что коннект закрыт и потомок, при попытке постучаться туда, ничего хорошего получить не должен.
Или я бред несу?
Офлайн
ZZZ, я пока не знаю, что тебе ответить. Питоновская часть проста как пять копеек - и все сводится к libpg.
Я смотрел ее реализацию очень бегло - незнакомый код и все такое. Соединение закрывается на PGfinish - это верно.
Код этой функции шлет сообщение _внутренней_ системе - нужно закрыться. Что дальше - не смотрел, извини.
Если это вопрос жизни или смерти - могу попытаться понять, как эта штука ведет себя в деталях.
Ответ “в общем” - так же, как и C код, использующий libpq. Никаких неожиданностей или трюков, как я вижу.
Офлайн
Андрей СветловОй нет, спасибо, это больше академический интерес по принципу: а вдруг кто-нибудь знает. :-)
Если это вопрос жизни или смерти
Офлайн
ZZZНе, в теории как раз соединением владеют два процесса, и оно закроется только тогда, когда оба процесса освободят этот ресурс.
в котором отрабатывается gc, который закрывает (в теории) соединение.
Офлайн
poltergeistС точки зрения сокета да, но с точки зрения более высокоуровневой части… Я думаю, что в норме соединение должно закрываться не убийством сокета, а посыланием пакета (сообщения), говорящим о том, что соединение закончено. Вот тут и проблема. :-)
Не, в теории как раз соединением владеют два процесса, и оно закроется только тогда, когда оба процесса освободят этот ресурс.
Офлайн
ZZZ
С моей точки зрения не стоит надеятся, что fork нормально отработает на объектах сложнее файла, сокета или shared memory. Т.е. новое подключение в потомке - это идеологически правильно.
fork отлично работает с объектами уровня ядра. Если поверх этого объекта (а то и нескольких - канал связи, объекты синхронизации) что-то надстроили в user space - результат в общем случае непредсказуемый. Если только заранее не была предусмотрена эта возможность.
Офлайн
Ну вот где-то так я и представил. :-)
Офлайн