Pergunta

Eu estou tentando prazo tclhttpd em um escravo intérprete mas ligeiramente modificado, de modo a correr dentro um tclkit. O código abaixo "runs" (Eu posso bater http: // localhost: 8015 ), mas nunca atinge a linha coloca à inferior, porque "o servidor não retorna, ele entra [vwait para sempre]". Mas quando eu tento "o depois 0 truque", por exemplo, prepending "depois 0" para a linha "$ httpd eval $ cmd", o servidor não é executado em tudo, então eu presumo "erros têm de ser tratados por bgerror"

No entanto eu não posso encontrar bons exemplos de como usar bgerror, além de meus pesquisa mostra que agora a convenção é usar "interp bgerror". Por favor, veja o primeiro par de exemplos retornados por http://www2.tcl.tk/_ / gsearch S = bgerror ?; o primeiro link contém o palavreado "preencher truques úteis e exemplos para usar bgerror", mas então não há amostras posso discernir como aplicar, e o segundo link conclui "Estou interessado em exemplos como isto é suposto ser usado."

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"
Foi útil?

Solução

Eu não entendo muito bem a pergunta que você está pedindo. Parece que seu objetivo é iniciar um servidor http em um intérprete, mas de alguma forma interagem com o intérprete principal. Isso está certo? Se assim for, o que isso tem a ver com bgerror?

Você está ciente de que, mesmo que você estiver executando o servidor em um interpretador separado, é não sendo executado em um segmento separado? Ou seja, você não pode (*) interagem com o intérprete principal, enquanto qualquer intérprete está bloqueada por uma vwait.

(*) pode, se sua interação toma a forma de widgets Tk que também tirar proveito do ciclo de eventos

Quanto à forma de usar bgerror, Há um par de maneiras que ele funciona. O mecanismo padrão chama a função 'bgerror", que você pode definir para fazer o que quiser. É preciso uma única corda (o texto de uma mensagem de erro) e faz algo com ele. Isso algo poderia ser a imprimir o erro para stdout, mostre-a em um diálogo, escrevê-lo em um arquivo, etc.

Como um exemplo, considere esta sessão interativa:

% 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

Você também pode registrar seu próprio manipulador de erro, conforme descrito na documentação para "bgerror interp". Este veio em tcl 8,5, embora tivesse um bug que não foi fixado até 8.5.3.

Por exemplo:

% 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

Será que isso ajuda responder a sua pergunta?

Outras dicas

Completamente editado com base nos comentários do OP ...

O depois 0 truque é a seguinte linha:

after 0 $httpd eval $cmd

O que isto faz é contar a interp para adicionar o comando em questão ($ http eval $ cmd) para a fila de eventos, o que significa que será executado uma vez que o ciclo de eventos é iniciado (ou devolvidos ao se ele já está iniciado). Você pode ver a dependência do ciclo de eventos na seguinte comentário a partir dessa página (por Jacob Levy):

Gostaria de salientar que isso depende do ciclo de eventos ser ativo.

Meu palpite é que você está executando um tclsh simples, o que significa que você nunca entrar no ciclo de eventos (o shell do desejo entra no ciclo de eventos no final do script, o shell Tcl não). A forma padrão para entrar no ciclo de eventos é executar o seguinte comando uma vez que você chegar ao final do seu código Tcl:

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

Dito isto, qualquer coisa que você tem após a vwait não será executado até que o ciclo de eventos é encerrado. Se quiser que o httpd para executar em paralelo ao seu código, você precisa se quer:

  • Usar vários segmentos, ou escreve sua ... o que realmente não é tão difícil
  • código a ser evento com base ... que exige que você entender, mesmo com base programação bem o suficiente para evitar que pedaços de código a partir de fome de tempo de execução.

Espero que ajude.

Se eu entendi corretamente o que você quer fazer, seu código deve ser semelhante ao que:

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

Desta forma você terá TclHttpd executando em um thread, sem se preocupar com o problema vwait

Se você também quer ser informado sobre qualquer erro durante a execução httpd, TclHttp envia todos os erros para um arquivo de log. Você pode configurar o caminho do Log fazendo:

Log_SetFile "/logs/httpd_log"

Você precisa ter o httpd :: pacote de log.

Espero que isso ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top