elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Scripting
| | |-+  ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event  (Leído 4,024 veces)
Drakaris

Desconectado Desconectado

Mensajes: 286


Todo lo que puedas imaginar, lo puedes crear.


Ver Perfil
¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
« en: 13 Noviembre 2021, 20:47 pm »

Buenas. Estoy haciendo una arquitectura servidor-multicliente con sockets in python3

Para esto utilizo la libreria multiprocessing
Código
  1. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2. sock.bind(("",PORT))
  3. sock.listen(CLIENTS)
  4. print(logFile().message(f"running ClassAdmin server, listen {CLIENTS} clients by port {PORT}...",True,"INFO"))
  5. sockSSL = context.wrap_socket(sock,server_side=True)
  6. childProcess = [] # This storages the childs processes
  7. event = multiprocessing.Event() # listening events of childs processes
  8. threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start()
  9. while sockSSL:
  10.    connection, address = sockSSL.accept()
  11.    subproccess = multiprocessing.Process(target=Client,name="client",args=(connection,address,event))
  12.    subproccess.start()
  13.    childProcess.append(subproccess)
  14.    time.sleep(1)
  15.  
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.

Código
  1. threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start()
  2.  

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
  1. @staticmethod
  2. def handlerEvent(event,childProcesses):
  3.    while True:
  4.        if event.is_set():
  5.            print(childProcesses)
  6.            # terminate child process
  7.            break
  8.        time.sleep(.5)
  9.  

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
  1. class Client:
  2. def __init__(self,conn,addr,event):
  3.    try:
  4.        self.conn, self.addr = conn, addr
  5.        print(logFile().message(f"Client {self.addr[0]} connected by port {self.addr[1]}", True, "INFO"))
  6.        self.__listenData()
  7.    except (KeyboardInterrupt,SystemExit) as err:
  8.        print(logFile().message(f"The client {self.addr[0]} left", True, "INFO"))
  9.    except BaseException as err:
  10.        type, object, traceback = sys.exc_info()
  11.        file = traceback.tb_frame.f_code.co_filename
  12.        line = traceback.tb_lineno
  13.        print(logFile().message(f"{err} in {file}:{line}", True, "ERROR"))
  14.    finally:
  15.        try:
  16.            self.conn.close()
  17.        except:
  18.            None
  19.        finally:
  20.            event.set()
  21. #[...]
  22. @staticmethod
  23. def handlerEvent(event,childProcesses):
  24.    while True:
  25.        if event.is_set():
  26.            print(childProcesses)
  27.            # terminate child process
  28.            break
  29.        time.sleep(.5)
  30.  

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
  1. self.conn.close()
  2.  
Y después se ejecutará el finally:
Código
  1. event.set()
  2.  

Por la cual el metodo handlerEvent de la clase Client detectará que el event es true
Código
  1. @staticmethod
  2. def handlerEvent(event,childProcesses):
  3.    while True:
  4.        if event.is_set():
  5.            print(childProcesses)
  6.            # terminate child process
  7.            break
  8.        time.sleep(.5)
  9.  
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?



En el cliente cuando hago el:
Código
  1. event.set()
  2.  
puedo obtener el PID del proceso hijo haciendo:
Código
  1.        finally:
  2.            print(os.getpid())
  3.            event.set()
  4.  

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.


En línea

Lo increible, no es lo que ves, sino como es
Drakaris

Desconectado Desconectado

Mensajes: 286


Todo lo que puedas imaginar, lo puedes crear.


Ver Perfil
Re: ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
« Respuesta #1 en: 6 Diciembre 2021, 12:23 pm »

En realidad, mi pregunta era.... Como matar un proceso zombie cuando el proceso cliente se cierra.








Para solucionar esto lo que hice es.... cuando esta escuchando clientes, además de iniciar un proceso hijo que será el cliente que se quiere conectar, creo un hilo en el proceso padre que estará en escucha de un evento que lo paso como parametro al proceso hijo del cliente.

Y este que se activa al querrer cerrar el cliente, gracias al hilo obtendrá el evento activado y se encargará de unir el proceso hijo del cliente al proceso padre. Después hace un break para acabar el hilo

Y finalmente se cierra el cliente.

Pasos que he hecho:

Primero, cuando escucho a los clientes, añado:
Código
  1. while sockSSL:
  2.    connection, address = sockSSL.accept()
  3.    eventChildStop = multiprocessing.Event()
  4.    subprocess = multiprocessing.Process(target=ClientListener, name="client", args=(connection, address,eventChildStop))
  5.  
  6.    # This thread is responsible of close the client's child process
  7.    threading.Thread(target=ClientListener.exitSubprocess,name="closeChildProcess",args=(eventChildStop,subprocess,)).start()
  8.    subprocess.start()
  9.    time.sleep(1)
  10.  

Después in the nuevo metodo de la clase ClientsListener, cambio:
Código
  1. @staticmethod
  2. def handlerEvent(event,childProcesses):
  3.    while True:
  4.        if event.is_set():
  5.            print(childProcesses)
  6.            # terminate child process
  7.            break
  8.        time.sleep(.5)
  9.  
por
Código
  1. # This method get as argument the process child. For join it at parent process
  2. @staticmethod
  3. def exitSubprocess(event,process):
  4.    while True:
  5.        if event.is_set():
  6.            process.join()
  7.            break
  8.        time.sleep(.5)
  9.  
cambio el nombre del metodo. No es que, añada otro, sino que cambio el nombre.

en el proceso hijo al cerrar le añado un time.sleep de un 1 segundo para que le de tiempo al hijo a unir el proceso hijo al proceso padre.
En el ultimo finally.
Código
  1. class ClientListener:
  2.    def __init__(self,conn,addr,event):
  3.        try:
  4.            self.conn, self.addr = conn, addr
  5.            self.nick = ""
  6.            self.__listenData()
  7.        except (KeyboardInterrupt,SystemExit) as err:
  8.            print(logFile().message(f"The host {self.nick} ({self.addr[0]}:{self.addr[1]}) left", True, "INFO"))
  9.        except BaseException as err:
  10.            type, object, traceback = sys.exc_info()
  11.            file = traceback.tb_frame.f_code.co_filename
  12.            line = traceback.tb_lineno
  13.            print(logFile().message(f"{err} in {file}:{line}", True, "ERROR"))
  14.        finally:
  15.            try:
  16.                ListClients().remove(self.conn)
  17.                self.conn.close()
  18.            except:
  19.                None
  20.            finally:
  21.                Client(self.conn,self.addr).registre(self.nick,"DISCONNECTED",False)
  22.                event.set()
  23.                # This will delay 1 second to close the proccess, for this gives time at exitSubprocess method to join the client's child process with the parent process
  24.                time.sleep(1)
  25.  

Muchas gracias por vuestra atención y tiempo  :D


En línea

Lo increible, no es lo que ves, sino como es
Danielㅤ


Desconectado Desconectado

Mensajes: 1.681


🔵🔵🔵🔵🔵🔵🔵


Ver Perfil
Re: ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
« Respuesta #2 en: 6 Diciembre 2021, 20:10 pm »

Hola compañero Drakaris, nos alegramos porque has solucionado tu problema y te agradecemos por dejar los pasos de la solución, que le puede servir a otros usuarios con el mismo o similar problema.


Saludos
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
OPEN EVENT
Software
Anmoar 1 3,381 Último mensaje 2 Mayo 2011, 02:32 am
por Novlucker
como hacer que un proceso ejecutado por otro proceso no sea hijo
Programación General
z_ane_666 0 2,063 Último mensaje 8 Diciembre 2011, 02:36 am
por z_ane_666
como hacer que un proceso ejecutado por otro proceso no sea hijo
Programación C/C++
z_ane_666 2 3,483 Último mensaje 9 Diciembre 2011, 15:24 pm
por z_ane_666
Listview + OnKeyPress event
.NET (C#, VB.NET, ASP)
Eleкtro 5 3,318 Último mensaje 6 Enero 2013, 04:23 am
por spiritdead
Fullcalendar con popover Bootstrap al crear event
Desarrollo Web
1304654 0 1,854 Último mensaje 17 Agosto 2015, 16:12 pm
por 1304654
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines