2010-09-12 5 views
0

При запуске tclsh и печатаю это:TCL зависает при попытке закрыть TCL трубы

close [open "|tclsh" w] 

он работает отлично.

Но, когда в ~/.tclshrc у вас есть package require Tk, та же линия делает tclsh HANG!

Та же проблема связана со всеми пакетами графического интерфейса, такими как Tk, Itk, Img, Iwidgets, но не с пакетами GUI, такими как Itcl, это хорошо.

Как исправить эту проблему? Дело в том, чтобы сделать tclsh не повесить, набрав close [open "|tclsh" w] с package require Tk в ~/.tclshrc.

Эта же проблема с wish. close [open "|wish" w] делает желание HANG (с пустым ~/.wishrc файлом)!

Я получил эту проблему как на 32, так и на 64 бит CentOS. У меня есть следующие версии пакетов: tcl-8.5.8, tk-8.5.8, img-1.3, itcl-3.4.b1, itk-3.3, iwidgets-4.0.1.

+0

У вас есть правильно настроенная переменная DISPLAY. Я имею в виду: можете ли вы успешно открыть графические программы из этой оболочки? – LatinSuD

+0

@LatinSuD - Да, программы GUI работают нормально. На самом деле желание (или backage требует Tk в tclsh) также открывает графический интерфейс. Проблема легко воспроизводится; Вы воспроизвели его на вашей стороне? – Vahagn

+0

Я просто попробовал это на 32-битном Ubuntu 10.04 tcl/tk 8.5.8, и он не зависал. Он отлично работает для меня. Вы уверены, что проблема не в чем-то другом? – slebetman

ответ

1

Моя мысль была в том, что она ждет желание завершить работу, как и на странице человека:

Если channelId является блокирующим канал команда трубопровода затем закройте Уэйтс для дочерних процессов для завершения ,

Поскольку пожелание входит в бесконечный цикл (цикл событий) и никогда не выходит, команда закрытия будет висеть. Вдоль тех же строк [пакет требует Tk] (я считаю) запускает цикл событий, поэтому приведет к такому же поведению.

Я признаю, однако, что это загрузка .tclshrc вообще, так как

Если существует файл .tclshrc (или tclshrc.tcl на платформах Windows) в домашнем каталоге пользователя, интерактивный tclsh оценивает файл как скрипт Tcl непосредственно перед чтением первой команды со стандартного ввода.

Мне кажется странным, что [open "| tclsh" w] завершается в интерактивной оболочке.

В качестве побочного примечания [pacakge require Tk] кажется действительно странным делом в .tclshrc. Теоретически, вы не всегда будете хотеть Tk (цикл окна и события) при запуске Tcl (т. Е. Приложений с командной строкой) ... и, когда вы этого хотите, вы знаете, что делаете. Кажется, каждому кажется, что это кажется странным для меня.

+0

Хорошо, рассмотрим случай с желанием. закрыть [open "| wish" w] делает желание висеть. Насколько я понял, из вашего ответа, вы говорите, что нет возможности исправить эту проблему. Это так ? – Vahagn

+0

Просто попросите сценарий вызвать exit. Поскольку он не может полагаться на «достижение конца сценария», чтобы программа закончилась (так как теперь она отправляется в глобальный цикл событий), вам нужно вызвать [exit], чтобы это произошло. – RHSeeger

+0

.tclshrc читается только в интерактивных сеансах; если есть скрипт, который был запущен для запуска, tclsh не касается файлов пользователя rc. Желание такое же, за исключением, конечно, файла .wishrc. (И для записи я никогда не определяю ничего в любом файле.) –

2

Приложения Tcl в основном выходят, когда они завершили свой сценарий, независимо от того, предоставляется ли оно интерактивно. Однако пакет Tk меняет ситуацию так, что когда конец скрипта достигнут, он вместо этого переходит в события обработки цикла. Если вы полагаетесь на конец файла, что приводит к выходу, это будет очень похоже на зависание, но на самом деле он просто ждет, когда приложение GUI закончится (чтобы он мог сообщить о статусе выхода подпроцесса).

Исправление состоит в том, чтобы обработать обработчик канала для stdin в подпроцессе.Там несколько способов, чтобы сделать это в деталях, но вот простой один, который может идти в конце основной части кода, который вы обычно отправить:

proc ReadFromStdin {} { 
    if {[gets stdin line] >= 0} { 
     uplevel "#0" $line 
    } elseif {[eof stdin]} { 
     exit 
    } else { 
     # Partial read; try later when rest of data available 
    } 
} 
fileevent stdin readable ReadFromStdin 

Это предполагает, что каждая строка представляет собой полный исполняемый командой; Конечно, это может быть неверно, но писать код для использования info complete для составления строк менее ясен и, возможно, здесь лишний. (Вы знаете, что вы действительно отправляете лучше, чем я ...)

Смежные вопросы