2015-01-12 2 views
1

Windows Tcl 8.5 응용 프로그램에서 Ctrl-C를 가로채는 데 문제가 있습니다. 내가 개발 한 확장 라이브러리에 콘솔 처리기를 추가했지만 항상 작동하지는 않습니다.Windows 콘솔의 Tcl 및 Ctrl-C

일부 Tcl 코드가 실행 중이면 모든 것이 정상입니다. 그러나 응용 프로그램이 사용자 입력을 기다리고 있으면 Ctrl-C를 눌러 종료합니다. 내 처리기가 호출되지만 동시에 (다른 스레드에서) Tcl REPL은 Tcl_Exit을 호출합니다. 이것은 모든 것을 정말로 엉망으로 만듭니다.

내가 알 수있는 한 REPL은 에 EOF이 발생했다고 잘못 생각하기 때문에 Tcl_Exit이 호출됩니다. 이것은 Ctrl-C를 누를 때 읽기 루틴이 리턴되고 읽은 바이트 수 (0)를 리턴한다는 결과입니다. REPL은이 조건을 EOF로 해석합니다.

이 문제를 쉽게 해결할 수 있습니까? Tcl 빌트인 채널을 버리고 나만의 채널을 제공 할 수는 있지만,이 간단한 문제는 과도한 것으로 보인다.

나는 twapi::set_console_control_handler을 시도했지만 전혀 작동하지 않는 것 같습니다. Ctrl-C를 누르면 항상 응용 프로그램이 종료되고 핸들러는 호출되지 않습니다.

+0

빠른 critcl 빌드 확장을 시도하여 SetConsoleCtrlHandler를 호출하고 동일한 효과를 얻습니다. 핸들러 함수가 호출되었지만 tclsh가 종료됩니다. 나는 twapi 버전에서 스크립트를 실행하기위한 이벤트를 발생시키고 이벤트가 처리되기 전에 종료되므로 스크립트를 호출하지 못한다고 생각합니다. 아마도 C 핸들러가 호출 될 것입니다. – patthoyts

답변

2

SetConsoleCtrlHandler에 대한 MSDN 설명서는 CTRL_C 처리가 별도로 처리되지만 콘솔 모드를 ENABLE_PROCESSED_INPUT으로 설정하여 해제 할 수 있다고 지적합니다. 그런 다음 Ctrl-C 이벤트를 키보드 입력으로보고합니다.

(load ctrl_c.dll ctrl_c; win32::SetCtrlHandler를 사용하여 인터프리터에로드 된 다음 critcl 코드는 종료하지 않고 제어-C 키보드 입력을 가로채는 날 수 있습니다 :

package require critcl 

namespace eval win32 { 
    critcl::ccode { 
#define STRICT 
#define WIN32_LEAN_AND_MEAN 
#define _WIN32_WINNT 0x0502 
#include <windows.h> 

BOOL CtrlHandler(DWORD dwEvent) 
{ 
    switch (dwEvent) 
    { 
     case CTRL_C_EVENT: 
     fprintf(stderr, "ctrl_c\n"); 
     return TRUE; 
     default: 
     return FALSE; 
    } 
} 
} 

    # Quick and dirty test CTRL_C interception in windows. 
    critcl::cproc SetCtrlHandler {} ok { 
     BOOL b = SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); 
     if (b) 
      b = SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); 
     return b ? TCL_OK : TCL_ERROR; 
    } 
} 

critcl -lib ctrl_c.tcl를 사용하여 컴파일 그러나

일단 Ctrl-C를이 있습니다.! 콘솔 입력은 사용자가 입력 한 내용을 더 이상 울리지 않습니다. 입력을 읽고 그에 따라 작동하지만 그 입력을 반향하지 않습니다. 세션 예 :

% load ctrl_c.dll ctrl_c 
% win32::SetCtrlHandler 
% ctrl_c 
8.6.1 
% -blocking 1 -buffering line -buffersize 4096 -encoding unicode -eofchar → -translation auto 
% -blocking 1 -buffering line -buffersize 4096 -encoding unicode -eofchar {} -translation crlf 
% 

표시되지 않은 것은 fconfigure stdinfconfigure stdout을 입력 한 곳입니다. 바라기를 이것은 당신의 솔루션 검색을 도울 수 있기를 바랍니다.

+1

'ENABLE_PROCESSED_INPUT'을 설정하는 것은 Unix 터미널에서 raw/noecho 모드를 설정하는 것과 같습니다. 타이머 이벤트를 사용하여 수 마이크로 초 내에 리셋하는 것으로 충분할까요? 나는 정말로 모른다 ... –

2

twapi :: set_console_control_handler에 대해서는 이벤트 루프가 실행 중이어야 효과적입니다. Tcl 스레드가 100ms 이내에 응답하지 않으면 Ctrl-C를 처리하는 스레드는 기본 OS 제공 핸들러에서 계속됩니다. 응답을받지 못하면 OS 처리기로 전달하지 않는 것이 기본값으로 변경되어야합니다.

+0

Tcl을 변경하기 위해 RFE를 추가했다. http://core.tcl.tk/tcl/tktview/e66e44444023ee253956979c54c905c6006f4540 –

+0

Ctrl-C를 EOF로 취급하지 않도록 Tcl 트렁크 (8.6.4 이후)를 업데이트했다. 콘솔. –

+0

감사합니다. 방금 최신 릴리스를 다운로드했고 Ctrl-C를 눌러도 프로그램이 즉시 종료되지 않습니다. –