Регистрация | Войти
Lisp — программируемый язык программирования
RSS
не работает вызов внешних программ SBCL+SLIME+WIN32
den73 - 30.06.2015 17:32, Сообщений - 8
Вот такая команда работает из буфера *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}>
; старый процесс не исчез, а новый добавился и ждёт его. all-threads покажет их оба.
; переходим в *inferior-lisp*
* (ff)
#<SB-IMPL::PROCESS :EXITED 0>
> (bt:all-threads)
; процессы ff и ff2 исчезли


den73 - 30.06.2015 18:06
[#] Ответ на комментарий от den73 30.06.2015 18:06
Странно, если после вызова run-program вызвать (finish-output *standard-output*), то всё работает несколько лучше. Но пока не удаётся запусить cmd. Вроде удавалось сегодня, но это было уже давно...
den73 - 30.06.2015 20:20
[#] Ответ на комментарий от den73 30.06.2015 20:20
Для длинных команд нужно несколько раз сделать finish-output. Что-то всё это подозрительно... Где бы найти место в SLIME, где не делается должным образом finish-output?
den73 - 30.06.2015 21:08
[#] Ответ на комментарий от den73 30.06.2015 21:08
Подобную же проблему обнаружил и в самом EMACS. Обходной путь для EMACS состоял в том, что я написал программку на дельфи, которая сама по себе является не консольной, но вызывает CreateProcess с флагом CREATE_NEW_CONSOLE. Эта программка используется как адаптер для запуска стороннего приложения. В этом случае потоков мы лишаемся (хотя это можно решить), но хотя бы есть возможность запустить.
den73 - 07.07.2015 12:21
[#] Ответ на комментарий от den73 07.07.2015 12:21
// 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;
den73 - 07.07.2015 12:25
[#] Ответ на комментарий от den73 30.06.2015 18:06
Есть мнение, что виснет на Windows из-за особенностей работы GetFileType, который вызывается для StdIn, StdOut и StdErr внутри msvcrt.dll на старте.  А GetFileType для каналов не возвращается до тех пор, пока там не появится что-нибудь для чтения.
amartynov - 07.07.2015 16:44
[#] Ответ на комментарий от amartynov 07.07.2015 16:44
А это тогда почему? "Для длинных команд нужно несколько раз сделать finish-output."
den73 - 07.07.2015 21:33
[#] Ответ на комментарий от den73 07.07.2015 21:33
Вот запостил исходник проги целиком: https://bugs.launchpad.net/sbcl/+bug/1470500
den73 - 11.07.2015 22:48
@2009-2013 lisper.ru