Как передать переменную сокета при использовании exe c () в Python? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть версия программы A, которая вызывает execve () для выполнения другой версии программы B, сохраняя тот же PID.

Эта программа A имеет объект сокета, и мы хотели бы, чтобы другая программа B получила доступ к тот же сокет для отправки некоторых данных в установленное соединение.

Проблема в том, что я не нашел способа успешно восстановить сериализованный сокет, я сохраняю его в файл, открывая файл снова в новая программа B, но это не тот же объект, неинициализирован и не имеет никаких установленных атрибутов, я использовал укроп и маринад.

Существует ли безопасный способ передачи переменных объектов при вызове exe c ()? Или способ получить ссылку на указатель объекта и передать этот указатель вперед?

Версия A:

#!/bin/env python
import os
import dill as pickle
import socket

print "Version A"
print os.getpid()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(("127.0.0.1",80))

with open('file1.pickle', 'wb') as handle:
    pickle.dump(s, handle)

os.execlp('python', 'python', 'verB.py')

Версия B:

#!/bin/env python
import os,pdb,sys
import dill as pickle
import socket

print "Version B"
print os.getpid()
infile = open('file1.pickle','rb')
infile.seek(0, 0)
s = pickle.load(infile)
infile.close()

s.send("mymessage")

s.close()


Разъем версии B s неинициализирован, как восстановить сокет?

1 Ответ

1 голос
/ 10 апреля 2020

В unix -подобных системах execve программы сохраняют дескрипторы открытых файлов, которые не отмечены FD_CLOEXEC. Вам нужно передать дескриптор файла (маленькое целое число) новому процессу. Python по умолчанию устанавливает файловые дескрипторы на закрытие c, поэтому, если ваш родительский процесс - процесс python, ему необходимо специально изменить этот флаг. Вы можете записать сокет fd в файл:

open("file1.txt", "w").write(str(s.fileno()))

, но чаще всего его можно передать в командную строку или добавить в окружение. Например, python вызывает python с сокетом, переданным в командной строке:

verA.py

import socket
import os
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("stackoverflow.com", 80))
os.set_inheritable(sock.fileno(), True)
os.execlp(sys.executable, "python", "verB.py", str(sock.fileno()))

verB.py

import socket
import sys

sock = socket.fromfd(int(sys.argv[1]), socket.AF_INET, socket.SOCK_STREAM)
sock.send(b"GET / HTTP/1.1\r\nHost:stackoverflow.com\r\n\r\n")
print(sock.recv(500))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...