终止GHCi

时间:2017-04-27 20:52:59

标签: haskell ghci

为了便于在处理错误输入时读取用户指定的文件,我已经写了这个函数:

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的默认安装。

1 个答案:

答案 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问题,但影响未知/多架构。)