как использовать Tcl (Interp) Bgerror - PullRequest
1 голос
/ 14 сентября 2009

Я пытаюсь запустить tclhttpd в подчиненном интерпретаторе , но слегка модифицирован для запуска в tclkit. Код ниже «запускается» (я могу нажать http://localhost:8015), но никогда не достигает строки пут внизу, потому что «сервер не возвращается, он входит [vwait forever]». Но когда я пытаюсь «трюк после 0 «Например, добавляя после 0» к строке «$ httpd eval $ cmd», сервер не запускается вообще, поэтому я предполагаю, что «ошибки должны обрабатываться bgerror»

Однако я не могу найти хороших примеров того, как использовать bgerror, плюс мои исследования показывают, что теперь принято использовать «interp bgerror». Посмотрите первые пару примеров, возвращаемых http://www2.tcl.tk/_/gsearch?S=bgerror;, первая ссылка содержит словоблудие «заполните полезные приемы и примеры использования bgerror», но затем я не могу найти примеров, как подать заявку, и вторая ссылка завершает «Мне интересны примеры, как это должно использоваться.»

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"

Ответы [ 3 ]

2 голосов
/ 14 сентября 2009

Полностью отредактировано на основе комментариев ОП ...

Трюк после 0 представляет собой следующую строку:

after 0 $httpd eval $cmd

Что это делает, это говорит interp добавить соответствующую команду ($ http eval $ cmd) в очередь событий, что означает, что она будет запущена после запуска цикла событий (или возврата к нему, если он уже запущен). Вы можете увидеть зависимость от цикла событий в следующем комментарии от этой страницы (Джейкоб Леви):

Должен заметить, что это зависит от активности цикла событий.

Я предполагаю, что вы используете простой Tclsh, что означает, что вы никогда не входите в цикл обработки событий (оболочка Wish входит в цикл обработки событий в конце сценария, а оболочка Tcl - нет). Стандартный способ войти в цикл обработки событий - выполнить следующую команду, как только вы доберетесь до конца кода Tcl:

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

При этом все, что у вас есть после vwait, не будет работать до тех пор, пока не завершится цикл обработки событий. Если вы хотите, чтобы httpd работал параллельно с вашим кодом, вам нужно:

  • Используйте несколько тем или напишите свой ... что на самом деле не так сложно
  • код должен быть основан на событиях ... что требует от вас понимания даже основанного на программировании достаточно хорошо, чтобы предотвратить потерю времени выполнения кода.

Надеюсь, это поможет.

1 голос
/ 24 сентября 2009

Я не совсем понимаю вопрос, который вы задаете. Похоже, ваша цель - запустить http-сервер в одном интерпретаторе, но каким-то образом взаимодействовать с основным интерпретатором. Это правильно? Если да, то как это связано с bgerror?

Знаете ли вы, что, хотя сервер запускается в отдельном интерпретаторе, он не работает в отдельном потоке? То есть вы не можете (*) взаимодействовать с основным интерпретатором, в то время как любой интерпретатор заблокирован vwait.

(*) вы можете, если ваше взаимодействие принимает форму Tk-виджетов, которые также используют цикл событий

Что касается того, как использовать bgerror, есть несколько способов, которыми он работает. Механизм по умолчанию вызывает функцию «bgerror», которую вы можете определить, чтобы делать все, что вы хотите. Он принимает одну строку (текст сообщения об ошибке) и что-то с ней делает. Что что-то может быть напечатано ошибка в стандартный вывод, показать ее в диалоговом окне, записать в файл и т. д.

В качестве примера рассмотрим этот интерактивный сеанс:

% 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

Вы также можете зарегистрировать свой собственный обработчик ошибок, как описано в документации к «interp bgerror». Это произошло в tcl 8.5, хотя в нем была ошибка 1017 *, которая не была исправлена ​​до 8.5.3.

Например:

% 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

Помогает ли это ответить на ваш вопрос?

1 голос
/ 24 сентября 2009

Если я правильно понял, что вы хотите сделать, ваш код должен выглядеть примерно так:

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

Таким образом, TclHttpd будет работать в потоке, не беспокоясь о проблеме vwait

Если вы также хотите получать информацию о любой ошибке во время выполнения httpd, TclHttp отправляет все ошибки в файл журнала. Вы можете настроить путь к журналу, выполнив:

Log_SetFile "/logs/httpd_log"

Вам необходим пакет httpd :: log.

Надеюсь, это поможет.

...