У меня есть процесс, который мой код запускает с subprocess.Popen()
, который пытается подключиться к сокету, который мой код также прослушивает. Проблема в том, что если код начинает прослушивать этот сокет первым, он не может запустить подпроцесс. Он был заблокирован sock.accept()
, и когда sock.accept()
истекает, он явно не слушает, когда запускается subprocess.Popen()
. Если код сначала запускает подпроцесс, он пытается подключиться к сокету, но затем терпит неудачу, прежде чем какой-либо код сможет его прослушать.
Теперь ... есть мысли о том, как я могу это сделать? Казалось бы, мне нужно начать слушать неблокирующим образом, а затем запустить процесс, но я немного сбит с толку, потому что даже если я использую select () для обработки очереди, в конце концов вызывается sock.accept () и таким образом блокирует код ... я думаю.
В любом случае, какое-то направление было бы очень удобно! Я бы предпочел не делать этого, но если это облегчает жизнь, мне тоже не суждено использовать Twisted.
Редактировать 1:
Я попытаюсь что-то сделать с помощью кода, мне нужно взглянуть на мои старые коммиты, чтобы найти рабочую версию. Хотя в принципе я не думаю, что мой код - это проблема. Мне кажется, я просто неправильно это реализую.
Например, если я запускаю свой слушатель сокетов и вручную, в оболочке, запускаю этот подпроцесс.Popen () процесс, который он подключает просто отлично. Это потому что оболочка уже слушает. Я верю моя проблема - просто курица и яйцо. В моем коде, по одному пути кода, если я запускаю процесс первым, он мгновенно завершается сбоем, потому что сервер сокетов не прослушивает пока . Однако, если я сначала запускаю сервер сокетов, он отключается, потому что он блокируется, и никакой подпроцесс не запускается, пока он не завершит блокировку . Мое решение, я полагаю, заключается в неблокирующем коде, но я очень не знаю, как этого добиться правильно. Я вижу много упоминаний о select()
, но они выглядят как , они будут блокироваться в той же точке, sock.accept()
. Я говорю «похоже», потому что мне еще предстоит реализовать версию select()
. Я могу ошибаться здесь, и если я, пожалуйста, дайте мне знать.
Редактировать 2:
Вот часть кода в сокете. Обратите внимание, что в настоящее время эта функция не блокируется.
90 # Create our socket stream to listen on.
91 serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
92
93 #serv.settimeout(5)
94 serv.setblocking(0)
95
96 # Bind the address.
97 serv.bind(('', self.PORT))
98 serv.listen(5)
99
100 try:
101 # Now start listening for a connection!
102 (self._sock, remote_address) = serv.accept()
103 except socket.timeout:
104 logger.debug('Socket connection failed!')
105 raise DBGPServerNotFoundError(
106 'No connection was established coming from '
107 '"%(address)s:%(port)i".' % {
108 'address':self.ADDRESS,
109 'port':self.PORT,
110 })
111 else:
112 logger.debug('Socket connection established! The other end of '
113 'the connection is at "%s:%i".' % remote_address)
114 finally:
115 serv.close()
А вот и ошибка ..
File "/home/lee/projects/vim-debug/repo/vimbug/dbgp.py", line 100, in connect
(self._sock, remote_address) = serv.accept()
File "/usr/lib/python2.6/socket.py", line 197, in accept
sock, addr = self._sock.accept()
error: [Errno 11] Resource temporarily unavailable
Код запуска подпроцесса находится в другом модуле (в частности, в модульном тесте), но здесь это для хорошей меры. Обратите внимание, что con
является контейнерным объектом, а con.connect()
является функцией для приведенного выше кода.
56 con.connect()
57 pydbgp_proc = subprocess.Popen(
58 ('pydbgp.py', '-d', 'localhost:%i' % OPTIONS['pydbgp_port'],
59 OPTIONS['debug_file']),
60 stdout=subprocess.PIPE,
61 stderr=subprocess.PIPE,)
Редактировать 3: Немного переписать код, чтобы попытаться подключиться к сокету до вызова sock.accept()
. Посмотрим, не получится ли:)
Редактировать 4:
Хорошо. Немного переписал код .. всё равно ошибка та же. Мысли? (Также .. этот мусор редактирования становится большим .. есть ли какой-нибудь предпочтительный способ в стеке потока делать эти большие обновления / правки?
Код:
77 def listen(self):
78 # Create our socket stream to listen on.
79 serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
80
81 #serv.settimeout(5)
82 serv.setblocking(0)
83
84 # Bind the address.
85 serv.bind(('', self.PORT))
86 serv.listen(5)
87 self.serv = serv
88
89 def accept(self):
90 (newsock, newaddr) = self.serv.accept()
Телефонный код:
57 con.listen()
58 pydbgp_proc = subprocess.Popen(
59 ('pydbgp.py', '-d', 'localhost:%i' % OPTIONS['pydbgp_port'],
60 OPTIONS['debug_file']),
61 stdout=subprocess.PIPE,
62 stderr=subprocess.PIPE,)
63 con.accept()
Ошибка:
File "/home/lee/projects/vim-debug/repo/vimbug/dbgp.py", line 90, in accept
(newsock, newaddr) = self.serv.accept()
File "/usr/lib/python2.6/socket.py", line 197, in accept
sock, addr = self._sock.accept()
error: [Errno 11] Resource temporarily unavailable
Мысли
Редактировать 5: Я изменил функцию принятия на следующую реализацию select()
, в результате чего была напечатана 'Not ready..?'
.
89 def accept(self):
90 rfds, wfds, xfds = select.select([self.serv], [], [], 1)
91
92 if self.serv in rfds:
93 print 'Read ready..?'
94 (newsock, newaddr) = self.serv.accept()
95 else:
96 print 'Not ready..?'