Para esto utilizo la libreria multiprocessing
Código
En este código, la variable 'event' is un evento de la libreria multiprocessing que esta en escucha de que algún proceso hijo lo active.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("",PORT)) sock.listen(CLIENTS) print(logFile().message(f"running ClassAdmin server, listen {CLIENTS} clients by port {PORT}...",True,"INFO")) sockSSL = context.wrap_socket(sock,server_side=True) childProcess = [] # This storages the childs processes event = multiprocessing.Event() # listening events of childs processes threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start() while sockSSL: connection, address = sockSSL.accept() subproccess = multiprocessing.Process(target=Client,name="client",args=(connection,address,event)) subproccess.start() childProcess.append(subproccess) time.sleep(1)
Código
threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start()
Ejecuto un hilo que ejecutará el metodo estatico handlerEvent de la clase Client que se encargará de ver si la variable 'event' es activado
Código
@staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
En el while ejecuto un subproceso, haciendo que para cada cliente que se conecte este se ejecutará en un proceso hijo.
La clase Client es la siguiente:
Código
class Client: def __init__(self,conn,addr,event): try: self.conn, self.addr = conn, addr print(logFile().message(f"Client {self.addr[0]} connected by port {self.addr[1]}", True, "INFO")) self.__listenData() except (KeyboardInterrupt,SystemExit) as err: print(logFile().message(f"The client {self.addr[0]} left", True, "INFO")) except BaseException as err: type, object, traceback = sys.exc_info() file = traceback.tb_frame.f_code.co_filename line = traceback.tb_lineno print(logFile().message(f"{err} in {file}:{line}", True, "ERROR")) finally: try: self.conn.close() except: None finally: event.set() #[...] @staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
La idea es la siguiente:
El cliente se conecta y este se ejecuta la clase Client en un proceso hijo. Y así para cada cliente que se conecte. En el segundo cliente se ejecuta la clase Client en otro proceso hijo y así consecutivamente....
Vale, pues. El init de la clase tengo try...except para si el cliente se cierra este ejecuta el exception (alguno de los dos). Pero siempre cuando se cierra un cliente se ejecutará el finally (el primero). Que se encargará de hacer:
Código
Y después se ejecutará el finally:
self.conn.close()
Código
event.set()
Por la cual el metodo handlerEvent de la clase Client detectará que el event es true
Código
y ejecutará lo que hay dentro del if. Mi idea es coger el PID del proceso hijo que ha hecho el event.set(). Pues así puedo hacer un for y matar el proceso que coincida con el PID. Pero como lo hago?
@staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
En el cliente cuando hago el:
Código
puedo obtener el PID del proceso hijo haciendo:
event.set()
Código
finally: print(os.getpid()) event.set()
Sí hago esto si me obtiene el PID del hijo, pues este PID tendría que enviarlo al handlerEvent() como puedo hacer esto?
Si alguíen tiene alguna idea de como puedo hacerlo o alguna alternativa, lo agradeceria.
Gracias.