Pregunta

Estoy tratando de ejecutar tclhttpd en un intérprete esclavo pero ligeramente modificado para ejecutarse dentro un tclkit El código a continuación " se ejecuta " (Puedo presionar http: // localhost: 8015 ) pero nunca llega a la línea de put en la parte inferior porque " el servidor no regresa, entra [espere para siempre] " ;. Pero cuando intento el truco después de 0, p. anteponer " después de 0 " a la línea " $ httpd eval $ cmd " ;, el servidor no se ejecuta en absoluto, por lo que supongo que bgerror debe manejar los errores "

Sin embargo, no puedo encontrar buenos ejemplos de cómo usar bgerror, además mi investigación muestra que ahora la convención es usar "interp bgerror". Consulte los primeros ejemplos devueltos por http://www2.tcl.tk/_ / gsearch? S = bgerror ; el primer enlace contiene el verborrea "completar trucos y ejemplos útiles para usar bgerror" pero entonces no hay muestras que pueda discernir cómo aplicar, y el segundo enlace concluye "Estoy interesado en ejemplos de cómo se supone que debe usarse".

package require starkit
starkit::startup

set httpd_args [list]
set httpd [interp create]
$httpd eval "set argc [llength $httpd_args]"
set cmdargv "set argv [list $httpd_args ]"
$httpd eval "set topdir $starkit::topdir"
$httpd eval $cmdargv

set cmd [list source [file join $starkit::topdir bin/httpd.tcl]]
$httpd eval $cmd

puts "if seeing this controlled has returned"
¿Fue útil?

Solución

No entiendo muy bien la pregunta que haces. Parece que su objetivo es iniciar un servidor http en un intérprete pero de alguna manera interactuar con el intérprete principal. ¿Está bien? Si es así, ¿qué tiene que ver eso con bgerror?

¿Sabe que aunque está ejecutando el servidor en un intérprete separado, no se ejecuta en un hilo separado? Es decir, no puede (*) interactuar con el intérprete principal mientras un intérprete está bloqueado por un vwait.

(*) puede, si su interacción toma la forma de widgets Tk que también aprovechan el bucle de eventos

En cuanto a cómo usar bgerror, hay un par de formas en que funciona. El mecanismo predeterminado llama a la función 'bgerror " que puedes definir para hacer lo que quieras. Toma una sola cadena (el texto de un mensaje de error) y hace algo con ella. Ese algo podría ser imprimir el error en stdout, mostrarlo en un cuadro de diálogo, escribirlo en un archivo, etc.

Como ejemplo, considere esta sesión interactiva:

% proc bgerror {s} {puts "hey! I caught an error: $s"}
% # after 30 seconds, throw an error
% after 30000 {error "this is an error"}
after#0
% # after 40 seconds, terminate the event loop
% after 40000 {set ::done 1}
after#1
% # start the event loop
% vwait ::done
hey! I caught an error: this is an error
% # this prompt appears after 40 seconds or so

También puede registrar su propio controlador de errores, como se describe en la documentación de "interp bgerror". Esto apareció en tcl 8.5, aunque tenía un error que no se solucionó hasta 8.5.3.

Por ejemplo:

% set foo [interp create]
interp0
% $foo eval {proc myErrorHandler {args} {puts "myErrorHandler: $args"}}
% $foo bgerror myErrorHandler
myErrorHandler
% # after 30 seconds, throw an error
% $foo eval {after 30000 {error "this is an error"}}
after#0
% # after 40 seconds, terminate the loop
% $foo eval {after 40000 {set ::done 1}}
after#1
% $foo eval {vwait ::done}
myErrorHandler: {this is an error} {-code 1 -level 0 -errorcode NONE -errorinfo {this is an error
    while executing
"error "this is an error""
    ("after" script)} -errorline 1}
% # this prompt appears after 40 seconds or so

¿Ayuda esto a responder su pregunta?

Otros consejos

Completamente editado en base a los comentarios del OP ...

El truco después de 0 es la siguiente línea:

after 0 $httpd eval $cmd

Lo que esto hace es decirle al interp que agregue el comando en cuestión ($ http eval $ cmd) a la cola de eventos, lo que significa que se ejecutará una vez que se inicie el bucle de eventos (o regrese a si ya se inició). Puede ver la confianza en el bucle de eventos en el siguiente comentario de esa página (por Jacob Levy):

  

Debo señalar que esto depende de que el ciclo de eventos esté activo.

Supongo que está ejecutando un Tclsh simple, lo que significa que nunca ingresa el bucle de eventos (el shell Wish ingresa al bucle de eventos al final del script, el shell Tcl no). La forma estándar de ingresar al bucle de eventos es ejecutar el siguiente comando una vez que llegue al final de su código Tcl:

# Enter the event loop and stay in it until someone 
# sets the "forever" variable to something
vwait forever

Dicho esto, todo lo que tenga después del vwait no se ejecutará hasta que se salga del bucle de eventos. Si desea que el httpd se ejecute en paralelo a su código, debe:

  • Usa múltiples hilos, o escribe tu ... que realmente no es tan difícil
  • el código se basará en eventos ... lo que requiere que usted comprenda incluso la programación basada lo suficientemente bien como para evitar que las partes del código pierdan tiempo de ejecución.

Espero que eso ayude.

Si he entendido correctamente lo que quiere hacer, su código debería ser similar a eso:

set httpd_id [thread::create -preserved]
thread::send $http_id "source [file join $starkit::topdir bin/httpd.tcl]"

De esta forma tendrás TclHttpd ejecutándose en un hilo, sin preocuparte por el problema de vwait

Si también desea recibir información sobre cualquier error durante la ejecución de httpd, TclHttp envía todos los errores a un archivo de registro. Puede configurar la ruta del registro haciendo:

Log_SetFile "/logs/httpd_log"

Necesita tener el paquete httpd :: log.

Espero que esto ayude.

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