Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Problema con threads al hacer un servidor.

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Intermedio
Mensaje Lun Jun 25, 2007 5:33 pm
creating021
Vive para Perl en Español
Vive para Perl en Español
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
Problema con threads al hacer un servidor. Responder citando

Hola.
Siguiendo el recipiente 17.14 de Perl CookBook (2nd edition) de hacer un servidor multitasking (uso Sockets y no IO::Sockets por algunos problemas y limitaciones).

La cosa es que al usarlo ciertas veces el servidor muere... sin dar error alguno.

El código es muy similar al del libro (la parte de thread es 100% igual) y me pregunto sí el problemas es threads y si es bueno hacerlo con threads.pm o si hay mejor forma de hacerlo (sin usar POE).

Gracias.
Mensaje Lun Jun 25, 2007 5:44 pm
creating021
Vive para Perl en Español
Vive para Perl en Español
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
Responder citando

El prolbemas está en perldoc (al parecer es esto)

Cita:
WARNINGS
A thread exited while %d other threads were still running

A thread (not necessarily the main thread) exited while there were still other threads running. Usually it's a good idea to first collect the return values of the created threads by joining them, and only then exit from the main thread.


No se que hacer...
Mensaje Lun Jun 25, 2007 8:31 pm
Perl user
Maestro Honorario
Maestro Honorario
Registrado: 03 Nov 2004
Mensajes: 385
Responder citando

Que tal,

Bueno en primera instancia, no has publicado nada de código como para saber qué está REALMENTE mal, pero... te puedo casi asegurar que efectivamente SI es el thread principal el que está muriendo antes que los demás terminen, y esto es un comportamiento érroneo (es decir, de mal diseño) si los otros threads que están vivos no son daemons.

Lo que te dice el manual es correcto, ya que tu thread principal (o el que los lanzó a todos los que quedan vivos) de alguna manera tiene que esperar a que los otros terminen por medio de join().

El uso de threads.pm está realmente vetado puesto que baja considerablemente el performance del intérprete de Perl y también hace que muchos módulos (principalmente los de XS) fallen o tengan comportamientos indefinidos. Otra cosa importante es que multitasking es diferente a multi-threaded, hay muchas técnicas para realizar aplicaciones multitareas asíncronas, y ello implica incluso el uso de Poll/epoll, select, kselect, etc (Qué son algunos mecanismos de los que usa POE) y son muy eficientes puesto que los eventos son proporcionados directamente por el kernel.

Lo que te recomiendo, si todavía quieres algo como threads.pm, es que uses el pragma 'forks' que implementa todo lo que te ofrece threads.pm, pero utilizando como el nombre lo indica, la llamada al sistema fork.

Lamentablemente el manejo de múltiples threads en Perl sigue teniendo un mal desarrollo y todavía está muy verde, y es por eso que se recomienda evitar su uso, los ithreads existen con el propósito de emular fork() y afines en sistemas Win32, pero no para generar aplicaciones multi-thread en producción.

Así que bueno, la recomendación es: usa forks o usa POE; POE sigue siendo la mejor opción, a menos que REALMEMENTE tu implementación necesite de un thread/fork.

Saludos,
Mensaje Sab Jun 30, 2007 3:28 pm
creating021
Vive para Perl en Español
Vive para Perl en Español
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
Responder citando

Perl:
use threads;
use IO::Socket;

my $listen = IO::Socket::INET->new(
   LocalPort => 80,
   ReuseAddr => 1,
   Listen => 10,
);

sub handle_connection {
  my $socket = shift;
  #código y más código...
}

while(my $socket = $listen->accept){
  async(\&handle_connection, $socket)->detach;
}


Bueno, el código es similar (como ya dije, estoy usando Socket y no IO::Socket).

Y según mi libro (Computer Science & Perl Programming) no es una buena idea por el tema de ports a otros OS (como Win32 y preOS X).

Supongo que lo mejor es hacerlo con fork... pero me surge una duda:
Viendo el código de Perl CoockBook (nueva mente) noto que usa POSIX.
¿Si lo hago así, sería portable a Win32 y OS X?

Gracias por los comentarios.
Mensaje Dom Jul 01, 2007 11:51 am
Perl user
Maestro Honorario
Maestro Honorario
Registrado: 03 Nov 2004
Mensajes: 385
Responder citando

creating021 escribió:
Perl:
use threads;
use IO::Socket;

my $listen = IO::Socket::INET->new(
   LocalPort => 80,
   ReuseAddr => 1,
   Listen => 10,
);

sub handle_connection {
  my $socket = shift;
  #código y más código...
}

while(my $socket = $listen->accept){
  async(\&handle_connection, $socket)->detach;
}


Bueno, el código es similar (como ya dije, estoy usando Socket y no IO::Socket).

Y según mi libro (Computer Science & Perl Programming) no es una buena idea por el tema de ports a otros OS (como Win32 y preOS X).

Supongo que lo mejor es hacerlo con fork... pero me surge una duda:
Viendo el código de Perl CoockBook (nueva mente) noto que usa POSIX.
¿Si lo hago así, sería portable a Win32 y OS X?

Gracias por los comentarios.


Mira... la elección de usar Socket e IO::Socket es realmente sin importancia, no creo que estés desarrollando una aplicación de misión crítica como para que el 0.02% de overhead de IO:Socket sobre Socket tenga alguna importancia. IO::Socket es solo un wrapper sobre Socket, el cual es a su vez un wrapper sobre bsd sockets

Y según tu libro, el cuál también tengo, no es buena idea qué? Si hablas de una llamada fork(), fork es accesible en cualquier sistema tipo UNIX, y está implementado para sistemas que no lo soportan por medio de cuestiones como ithreads (por eso es costoso...), así que... ESO es portable.

Y no sé a qué recipe del Perl Cookbook te refieres, pero yo hablaba de forks, el pragma, no fork() la llamada al sistema. Lee nuevamente mi comentario y verifica por qué mencioné forks (como pragma).

Otra alternativa es utilizar Coroutines, alternativa muy buena para eventos asíncronos, que no requiere de sincronización ni locking.

Saludos,
Mensaje Dom Jul 01, 2007 1:42 pm
creating021
Vive para Perl en Español
Vive para Perl en Español
Registrado: 23 Feb 2006
Mensajes: 498
Ubicación: Frente al monitor
Responder citando

Perl_user escribió:
Mira... la elección de usar Socket e IO::Socket es realmente sin importancia, no creo que estés desarrollando una aplicación de misión crítica como para que el 0.02% de overhead de IO:Socket sobre Socket tenga alguna importancia. IO::Socket es solo un wrapper sobre Socket, el cual es a su vez un wrapper sobre bsd sockets


Solo quería aclarar las diferencias y tienes mucha razón en esto, realment no importa.

Perl_user escribió:
Y según tu libro, el cuál también tengo, no es buena idea qué? Si hablas de una llamada fork(), fork es accesible en cualquier sistema tipo UNIX, y está implementado para sistemas que no lo soportan por medio de cuestiones como ithreads (por eso es costoso...), así que... ESO es portable.


No, no fork, Threads.pm en Perl 5.005_03... no lo aclaré (notese, Threads y no treads).
La pregunta era para POSIX, pero ya que no lo uso, no importa... de todos modos encontré (ya no tengo el link) lo que si y no era soportado en diferentes OS las funciones de POSIX.

Perl_user escribió:
Y no sé a qué recipe del Perl Cookbook te refieres, pero yo hablaba de forks, el pragma, no fork() la llamada al sistema. Lee nuevamente mi comentario y verifica por qué mencioné forks (como pragma).


17.algo, uno que usa fork() y POSIX...
Resulta que solucioné el problema con fork(), sin POSIX y actualmente funciona sin problema.

Cualquier módulo (de los que has nombrados) logran la facilidad de programar el servidor con muy buena calidad.

Muchas gracias por todo esto, me ha sido de mucha ayuda.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Intermedio Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group