Question

J'essaie de exécuter tclhttpd dans un interpréteur d'esclaves , mais légèrement modifié pour pouvoir être exécuté dans un tclkit. Le code ci-dessous " s'exécute " (Je peux appuyer sur http: // localhost: 8015 ) mais je n'atteins jamais la ligne de vente en bas, car "le serveur ne revient pas, il entre [vwait pour toujours] ". Mais quand j'essaie "le truc après 0", par ex. en attente "après 0" sur la ligne "$ httpd eval $ cmd", le serveur ne s'exécute pas du tout, donc je suppose que "les erreurs doivent être traitées par bgerror"

Cependant, je ne trouve pas de bons exemples d'utilisation de bgerror. De plus, mes recherches montrent que la convention consiste désormais à utiliser "interp bgerror". Veuillez consulter les deux premiers exemples renvoyés par http://www2.tcl.tk/_ / gsearch? S = bgerror ; le premier lien contient le verbiage "Remplissez astuces utiles et exemples d'utilisation de bgerror". mais alors il n’ya pas d’échantillons que je puisse discerner comment appliquer, et le deuxième lien conclut: «Je suis intéressé par des exemples de la manière dont cela est censé être utilisé."

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"
Était-ce utile?

La solution

Je ne comprends pas très bien la question que vous posez. Il semble que votre objectif soit de démarrer un serveur http dans un seul interpréteur, tout en interagissant avec l’interprète principal. Est-ce correct? Si oui, qu'est-ce que cela a à voir avec bgerror?

Êtes-vous conscient du fait que même si vous exécutez le serveur dans un interpréteur séparé, pas ne s'exécute pas dans un thread séparé? Autrement dit, vous ne pouvez pas (*) interagir avec l'interpréteur principal tant que l'un des interprètes est bloqué par un vwait.

(*) vous pouvez, si votre interaction prend la forme de widgets Tk qui tirent également parti de la boucle d'événements

En ce qui concerne l'utilisation de bgerror, cela fonctionne de plusieurs manières. Le mécanisme par défaut appelle la fonction 'bgerror " que vous pouvez définir pour faire ce que vous voulez. Il faut une seule chaîne (le texte d'un message d'erreur) et fait quelque chose avec. Ce quelque chose pourrait être d’afficher l’erreur sur stdout, de la montrer dans une boîte de dialogue, de l’écrire dans un fichier, etc.

A titre d'exemple, considérons cette session interactive:

% 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

Vous pouvez également enregistrer votre propre gestionnaire d'erreurs, comme décrit dans la documentation de "interp bgerror". Cela est arrivé dans tcl 8.5, bien qu'il y ait un bug qui n'a pas été corrigé jusqu'à 8.5.3.

Par exemple:

% 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

Est-ce que cela aide à répondre à votre question?

Autres conseils

Complètement modifié en fonction des commentaires du PO ...

Le tour après 0 est la ligne suivante:

after 0 $httpd eval $cmd

Cela a pour effet d'indiquer à l'interp d'ajouter la commande en question ($ http eval $ cmd) à la file d'attente des événements, ce qui signifie qu'elle sera exécutée une fois que la boucle d'événements est démarrée (ou renvoyée à si elle est déjà commencée). Vous pouvez voir la confiance accordée à la boucle d'événement dans le commentaire suivant de cette page (par Jacob Levy):

  

Je dois noter que cela dépend de la boucle d'événement active.

Mon hypothèse est que vous exécutez un Tclsh en clair, ce qui signifie que vous n'entrez jamais dans la boucle d'événement (le shell Wish entre dans la boucle d'événement à la fin du script, pas le shell Tcl). La méthode standard pour entrer dans la boucle d'événements consiste à exécuter la commande suivante une fois que vous arrivez à la fin de votre code Tcl:

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

Cela étant dit, tout ce que vous avez après le vwait ne sera exécuté qu'après la sortie de la boucle d'événements. Si vous voulez que httpd soit exécuté parallèlement à votre code, vous devez soit:

  • Utilisez plusieurs discussions ou écrivez votre ... ce qui n'est vraiment pas si difficile
  • le code doit être basé sur des événements ... ce qui nécessite que vous compreniez suffisamment la programmation, même basée sur les bases, pour empêcher les morceaux de code de manquer de temps d'exécution.

L’espoir que cela aide.

Si j'ai bien compris ce que vous voulez faire, votre code devrait ressembler à cela:

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

De cette manière, TclHttpd s'exécutera dans un thread, sans vous soucier du problème vwait

Si vous souhaitez également être informé de toute erreur lors de l'exécution de httpd, TclHttp envoie toutes les erreurs dans un fichier journal. Vous pouvez configurer le chemin du journal en effectuant:

Log_SetFile "/logs/httpd_log"

Vous devez disposer du package httpd :: log.

J'espère que cela vous aidera.

scroll top