Многопроцессорность Python и сокеты не закрываются - PullRequest
3 голосов
/ 21 декабря 2010

Я испытываю странное поведение при использовании многопроцессорности и сокета на Python.Я имею дело с фрагментом кода, похожим на тот, который я публикую ниже (я много упростил, пытаясь быть наивным).

Код порождает три процесса: один процесс ничего не делает, другойПроцесс запускает третий, который будет прослушивать сокет.Если я прекращаю процесс «слушателя», сокет остается открытым (я вижу его там с помощью netstat).

  • Если я удаляю (или останавливаю) процесс «DoNothing», это работает.
  • Если я переключаю все на многопоточность. Вот так, это работает, но
  • Если я оставляю DoNothing как процесс и переключаю сервер и средство запуска на многопоточность. Thread, проблема сохраняется.

У кого-нибудь есть подсказка, почему сокет все еще открыт?Есть ли какие-либо проблемы, связанные с многопроцессорностью и сокетами?

Я использую Python 2.6.6, работающий на Linux.

Большое спасибо, Альваро.

import time
from multiprocessing import Process, Event

import socket

class Server(Process):
    def __init__(self, port):
        super(Server, self).__init__()

        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.bind(("127.0.0.1",port))
        self.s.listen(1)
        self.s.settimeout(10)
        self.is_stop = Event()
        self.is_stop.clear()

    def run(self):
        while not self.is_stop.is_set():
            print "Server: running (pid %s)" % self.pid 
            time.sleep(1)
        print "Server: exiting"

    def stop(self):
        self.is_stop.set()
        self.s.close()

class Launcher(Process):
    def __init__(self):
        super(Launcher, self).__init__()
        self.srv = Server(9999)
        self.srv.start()

    def run(self):
        print "Launcher pid %s" % self.pid
        while True:
            time.sleep(1)

    def stop(self):
        print "Launcher: I'm stopping the server"
        self.srv.stop()
        self.srv.terminate()
        self.srv.join()
        print "Launcher: server stopped"

class DoNothing(Process):
    def __init__(self):                
        super(DoNothing, self).__init__()

    def run(self):
        while True:
            time.sleep(1)


l = Launcher()
l.start()

dn = DoNothing()
dn.start()

time.sleep(2)

print " Stop launcher "
l.stop()

while True:
    time.sleep(1)

РЕДАКТИРОВАТЬ:

Соответствующий netstat -lnp вывод:

tcp        0      0 127.0.0.1:9999          0.0.0.0:*               LISTEN      7183/python

Я заметил, что pid, показанный в netstat, отличается от родительского процесса (когда сервер процессазапущен) на модуль запуска (когда сервер остановлен).

Ответы [ 2 ]

2 голосов
/ 21 декабря 2010

Чтобы устранить непосредственную проблему (сокет не выключается), добавьте self.s.shutdown(socket.SHUT_RDWR) к методу Server.stop:

def stop(self):
    self.is_stop.set()
    self.s.shutdown(socket.SHUT_RDWR) 
    self.s.close()
1 голос
/ 21 декабря 2010

Я не эксперт по пакету multiprocessing, но может показаться, что конструктор Process вызывается в контексте родительского процесса (то есть до fork ). Если это так, то отсюда следует, что это самый верхний процесс в вашей иерархии, который выполняет bind. Дочерние процессы, вероятно, наследуют сокет.

Что произойдет, если вы переместите все, что связано с self.s (bind и др.) В Server.run?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...