为了便于在处理错误输入时读取用户指定的文件,我已经写了这个函数:
readGetFile :: IO FilePath -> IO String
readGetFile getName =
catch (getName >>= readFile) (\e->do
let err = show (e :: IOException)
printf "Couldn't open file %v. Please enter a valid filename.\n" err
readGetFile getName >>= return)
这个问题不是关于这个功能,而是用来说明这一点。
如果我从GHCi调用此函数,并最终输入一个好的文件名,它会按预期工作。但是,如果我试图通过点击 CTRL - C 来提前终止它,那就会发生奇怪的事情。
*Input> readGetFile getLine
{BadFile.jpeg
}Couldn't open file BadFile.jpeg: openFile: does not exist (No such file or directory). Please enter a valid filename.
{^C}Couldn't open file <stdin>: hGetLine: end of file. Please enter a valid filename.
{^C}CouInterrupted.
ldn't p*Input> e file <stdin>: hGetLine: end of file. Please enter a valid filename.
{^C}Couldn't open file <stdin>: hGetLine: end of file. Please enter a valid filename.
*Input> {
}Couldn't open file : openFile: does not exist (No such file or directory). Please enter a valid filename.
请注意{}
中的文字是由我输入的(我没有输入{}
)。 {^C}
我只是按 CTRL - C 。
显然,即使GHCi试图恢复运行,递归也会继续运行并从stdin读取。
如何从GHCi中终止此循环?
注意:我已完成hSetBuffering stdout NoBuffering
。这个问题与readGetFile
的实施无关,答案必须回答上面的粗体问题。如果答案提供了为什么它在键盘中断方面更好,同时仍能实现预期目标,那么可能会提供更好的方法来实现readGetFile
。 < / p>
这显然只发生在Windows上。我在Windows上运行Haskell Platform Core的默认安装。
答案 0 :(得分:0)
看起来这是a known issue in GHCi。
感谢您的报告,这似乎与mingw-w64有关 运行。我还没有缩小它,但基本上是一些东西 似乎正在吃这些事件而且它永远不会达到ghci。
CtrlHandler
永远不会被调用。以下示例显示了该问题。它使用时编译 Microsoft编译器,但没有与mingw-w64的GHC。
#include <windows.h> #include <stdio.h> BOOL CtrlHandler( DWORD fdwCtrlType ) { switch( fdwCtrlType ) { // Handle the CTRL-C signal. case CTRL_C_EVENT: printf( "Ctrl-C event\n\n" ); Beep( 750, 300 ); return( TRUE ); // CTRL-CLOSE: confirm that the user wants to exit. case CTRL_CLOSE_EVENT: Beep( 600, 200 ); printf( "Ctrl-Close event\n\n" ); return( TRUE ); // Pass other signals to the next handler. case CTRL_BREAK_EVENT: Beep( 900, 200 ); printf( "Ctrl-Break event\n\n" ); return FALSE; case CTRL_LOGOFF_EVENT: Beep( 1000, 200 ); printf( "Ctrl-Logoff event\n\n" ); return FALSE; case CTRL_SHUTDOWN_EVENT: Beep( 750, 500 ); printf( "Ctrl-Shutdown event\n\n" ); return FALSE; default: return FALSE; } } int main( void ) { if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) { printf( "\nThe Control Handler is installed.\n" ); printf( "\n -- Now try pressing Ctrl+C or Ctrl+Break, or" ); printf( "\n try logging off or closing the console...\n" ); printf( "\n(...waiting in a loop for events...)\n\n" ); while( 1 ){ } } else { printf( "\nERROR: Could not set control handler"); return 1; } return 0; }
这在msys2控制台中也不起作用,即使看起来如此。 在msys2的情况下,bash正在禁用
ENABLE_PROCESSED_INPUT
系统未处理CTRL+C
,并将其报告为输入 流。然后Bash只是强行终止这个过程。在GHCi的情况下,运行时明显发生了一些事情 因为它突然开始分配大量的内存和 进入某种僵局。所以这里有两个不同的问题。
(注意:我没有创建此问题。它似乎是第一次报告2017-03-01。该问题目前被标记为不是x86问题,但影响未知/多架构。)