Вот такая команда работает из буфера *inferior-lisp*, но не работает из *slime-repl sbcl*.
Я что-то делаю не так или это бага?
(let ((sb-impl::*default-external-format* :cp866)) (sb-ext:run-program "ipconfig.exe" nil :input nil :output nil :error nil :wait t :external-format :cp866 :directory "c:\\" :search t))sbcl взят в виде msi 1.2.12
Не знаю, верно ли я назначаю форматы, но они всё равно ничего не меняют.
Интересно, что если после зависания SLIME подать вторую такую же команду в буфере *inferior-lisp*, то она "пропинывает" зависшую и всё продолжает работать нормально. Вот как это примерно выглядит (звёздочка - это введено в *inferior-lisp*, ">" - в SLIME. Соответственно - две звёздочки - это вывод *inferior-lisp, ">>" - вывод SLIME.
>
(defun ff () (let ((sb-impl::*default-external-format* :cp866)) (sb-ext:run-program "ipconfig.exe" nil :input nil :output nil :error nil :wait t :external-format :cp866 :directory "c:\\" :search t)))>
(quicklisp:quickload :bordeaux-threads)>
(bt:make-thread #'ff :name "running ff")
#<SB-THREAD:THREAD "running ff" RUNNING {245C7B61}>
>
(bt:all-threads)
(#<SB-THREAD:THREAD "running ff" RUNNING {245C7B61}> #<SB-THREAD:THREAD "new-repl-thread" RUNNING {24315379}> #<SB-THREAD:THREAD "auto-flush-thread" RUNNING {2588EC79}> #<SB-THREAD:THREAD "swank-indentation-cache-thread" RUNNING {24D84169}> #<SB-THREAD:THREAD "reader-thread" RUNNING {24D84019}> #<SB-THREAD:THREAD "control-thread" RUNNING {24D83B39}> #<SB-THREAD:THREAD "Swank Sentinel" RUNNING {24C141B9}> #<SB-THREAD:THREAD "main thread" RUNNING {240CE949}>); запущен, а ему давно пора бы закончиться, дело там секундное
>
(bt:make-thread #'ff :name "running ff 2")
#<SB-THREAD:THREAD "running ff 2" waiting on: #<MUTEX "Lock for active processes." owner: #<SB-THREAD:THREAD "running ff" RUNNING {245C7B61}>> {247DABF1}>
*
(ff)
#<SB-IMPL::PROCESS :EXITED 0>
>
(bt:all-threads)
Странно, если после вызова run-program вызвать (finish-output *standard-output*), то всё работает несколько лучше. Но пока не удаётся запусить cmd. Вроде удавалось сегодня, но это было уже давно...
Для длинных команд нужно несколько раз сделать finish-output. Что-то всё это подозрительно... Где бы найти место в SLIME, где не делается должным образом finish-output?
Подобную же проблему обнаружил и в самом EMACS. Обходной путь для EMACS состоял в том, что я написал программку на дельфи, которая сама по себе является не консольной, но вызывает CreateProcess с флагом CREATE_NEW_CONSOLE. Эта программка используется как адаптер для запуска стороннего приложения. В этом случае потоков мы лишаемся (хотя это можно решить), но хотя бы есть возможность запустить.
// http://www.sql.ru/forum/242379/zapusk-bat-fayla, автор - RIM1977
// (C) Денис Будяк 2015
{$i лицензия MIT}
{uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs }
// собирается Delphi 2007
function FileExec( const CmdLine: String; bHide, bWait: Boolean): Boolean;
var
StartupInfo : TStartupInfo;
ProcessInfo : TProcessInformation;
begin
// MsgBox2(CmdLine);
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
if bHide then
wShowWindow := SW_HIDE
else
wShowWindow := SW_SHOWNORMAL;
end;
Result := CreateProcess(nil, PChar(CmdLine), nil, nil, False,
NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE, nil, nil, StartupInfo, ProcessInfo);
if Result then
CloseHandle(ProcessInfo.hThread);
if bWait then
if Result then
begin
WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
end;
if Result then
CloseHandle(ProcessInfo.hProcess);
end;
Есть мнение, что виснет на Windows из-за особенностей работы GetFileType, который вызывается для StdIn, StdOut и StdErr внутри msvcrt.dll на старте. А GetFileType для каналов не возвращается до тех пор, пока там не появится что-нибудь для чтения.
А это тогда почему? "Для длинных команд нужно несколько раз сделать finish-output."
Вот запостил исходник проги целиком: https://bugs.launchpad.net/sbcl/+bug/1470500