Pregunta

El Trenzado de la documentación me llevó a creer que estaba bien para combinar las técnicas tales como reactor.spawnProcess() y threads.deferToThread() en la misma aplicación, que el reactor manejar esta elegante y debajo de las cubiertas.En realidad tratando de ello, me di cuenta de que mi aplicación de los interbloqueos.El uso de múltiples hilos por sí mismos, o los procesos hijos de por sí, todo está bien.

Buscando en el reactor de la fuente, me parece que la SelectReactor.spawnProcess() método simplemente llama os.fork() sin ninguna consideración por las múltiples hilos que podrían estar en ejecución.Esto explica la interbloqueos, porque comenzar con la llamada a la os.fork() usted tendrá dos procesos con múltiples subprocesos simultáneos ejecutando y haciendo quién sabe qué con los mismos descriptores de archivo.

Mi pregunta ENTONCES es, ¿cuál es la mejor estrategia para resolver este problema?

Lo que tengo en mente es subclase SelectReactor, por lo que es un singleton y llamadas os.fork() sólo una vez, inmediatamente cuando se crea una instancia.El proceso hijo se ejecutará en segundo plano y actuar como un servidor para el padre (el uso de la serialización de objetos sobre tuberías para comunicarse de ida y vuelta).El padre continúa para ejecutar la aplicación y puede usar los hilos como se desee.Las llamadas a spawnProcess() en el padre se delega en el proceso hijo, que será la garantía de tener sólo un subproceso en ejecución y por lo tanto puede llamar os.fork() de forma segura.

Alguien ha hecho esto antes?Es allí una manera más rápida?

¿Fue útil?

Solución 3

Volviendo a este tema después de algún tiempo, me encontré con que si yo hago esto:

reactor.callFromThread(reactor.spawnProcess, *spawnargs)

en lugar de esto:

reactor.spawnProcess(*spawnargs)

entonces el problema desaparece en mi pequeña prueba.Hay un comentario en el Trenzado de la documentación "Mediante el uso de Procesos" que me llevó a probar esto:"La mayor parte del código en el Trenzado no es thread-safe.Por ejemplo, la escritura de datos en el transporte de un protocolo no es thread-safe."

Tengo la sospecha de que las otras personas Jean-Paul mencionados estaban teniendo este problema puede ser la fabricación de un error similar.La responsabilidad es la aplicación para hacer cumplir ese reactor y otras llamadas a la API dentro de la correcta hilo.Y al parecer, con muy pocas excepciones, los "hilo" es casi siempre el reactor principal del hilo.

Otros consejos

¿Cuál es la mejor estrategia para resolver este problema?

Presentar un ticket (tal vez después de el registro de describir el problema, de preferencia con un reproducable caso de prueba (para la máxima precisión).A continuación, puede haber alguna discusión acerca de cuál es la mejor forma (o formas diferentes plataformas puede exigir solución diferente) para la implementación de lo que podría ser.

La idea de crear de inmediato un proceso hijo para ayudar con otro niño el proceso de creación ha sido planteado antes, para resolver el problema de rendimiento de los alrededores niño el proceso de la cosecha.Si ese enfoque ahora resuelve dos problemas, que empieza a parecer un poco más atractivo.Uno de los posibles dificultades con este método es que spawnProcess de forma sincrónica devuelve un objeto que proporciona el hijo del PID y permite el envío de señales a ella.Esto es un poco más de trabajo para implementar si hay un proceso intermedio en el camino, ya que el PID tendrá que ser comunicados al proceso principal antes de spawnProcess devuelve.Un desafío similar será el apoyo a la childFDs argumento, ya que no será posible solamente para heredar los descriptores de archivo en el proceso hijo.

Una solución alternativa (que puede ser un poco más hackish, pero que también tienen menos problemas de aplicación) podría ser llamar sys.setcheckinterval con un gran número antes de llamar os.fork, y , a continuación, restaurar el original intervalo de comprobación en el proceso padre solo.Esto debería ser suficiente para evitar cualquier cambio de subproceso en el proceso hasta que la os.execvpe se lleva a cabo, la destrucción de todos los subprocesos adicionales.Esto no es completamente correcto, ya que dejará de ciertos recursos (como los mutexes y condiciones) en un mal estado, pero la utilización de estos con deferToThread no es muy común, así que tal vez que no afectan a su caso.

El consejo Jean-Paul da en su respuesta es buena, pero esta debe el trabajo (y en la mayoría de los casos).

En primer lugar, Trenzado utiliza hilos para la resolución de nombre de host así, y definitivamente, he utilizado los subprocesos de Trenzado de los procesos que también hacen las conexiones de cliente.Así que esto puede funcionar en la práctica.

Segundo, fork() no crear varios hilos en el proceso hijo. De acuerdo a la norma que describe fork(),

Un proceso que debe ser creado con un solo hilo.Si un proceso multiproceso llamadas fork(), el nuevo proceso deberá contener una réplica del subproceso de llamada ...

Ahora, eso no quiere decir que no se no posibles problemas de subprocesamiento múltiple con spawnProcess;la norma también dice:

...para evitar errores, el proceso hijo puede ejecutar solo async-la señal-la seguridad de las operaciones hasta el momento en que una de las funciones exec se llama ...

y yo no creo que haya nada para asegurarse de que sólo async-la señal-la seguridad de las operaciones se utilizan.

Así que, por favor, ser más específicos en cuanto a tu problema exacto, ya que no es un subproceso con hilos de ser clonado.

fork() en Linux sin duda deja el proceso hijo con un solo hilo.

Supongo que eres consciente de que, cuando el uso de hilos en el Trenzado, el ÚNICO Trenzado de la API de que los hilos están autorizados a llamar es callFromThread?Todos los demás Trenzado Api sólo debe ser llamado desde el principal, el reactor hilo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top