Вопрос

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

Однако я не могу найти хороших примеров того, как использовать bgerror, плюс мои исследования показывают, что теперь принято использовать "interp bgerror".Пожалуйста, ознакомьтесь с первой парой примеров, возвращенных http://www2.tcl.tk/_/gsearch ?S=ошибка;первая ссылка содержит формулировку "заполните полезные приемы и примеры использования 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"
Это было полезно?

Решение

Я не совсем понимаю вопрос, который вы задаете. Похоже, ваша цель - запустить 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, хотя в ней была ошибка это не было исправлено до 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

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

Другие советы

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

Трюк после 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 выполнялся параллельно вашему коду, вам необходимо либо:

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

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

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

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.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top