如何使用haskell处理窗口上的信号?

时间:2012-04-26 12:13:53

标签: haskell signals

Windows上有类似System.Posix的内容吗?

我希望下面的代码在Windows上运行,我应该更改吗?

import IO
import Control.Exception hiding (catch)
import Control.Concurrent
import Network
import System.Posix   ---cannot be run on windows.

main = withSocketsDo (installHandler sigPIPE Ignore Nothing >> main')
    --so the signal handler cannot be used

main' = listenOn (PortNumber 9900) >>= acceptConnections

acceptConnections sock = do
        putStrLn "trying to accept" -- debug msg
        conn@(h,host,port) <- accept sock
        print conn -- debug msg
        forkIO $ catch (talk conn `finally` hClose h) (\e -> print e)
        acceptConnections sock

talk conn@(h,_,_) = hGetLine h >>= hPutStrLn h >> hFlush h >> talk conn

例如,如果我希望程序在ctrl + c时退出,我必须为SIGINT添加一个处理程序,所以在c ++中,写一些这样的代码:

void callback(int sig) 
{ 
   // printf("catch\n"); 
} 
... 
signal(SIGINT,callback); 

但是我不知道如何在haskell中这样做,使用FFI?

4 个答案:

答案 0 :(得分:4)

import Foreign
import Foreign.C.Types

type Handler = CInt->IO ()
foreign import ccall "wrapper"
  genHandler:: (Handler) -> IO (FunPtr Handler)

foreign import ccall safe "signal.h signal"
        install:: CInt->FunPtr Handler->IO CInt
main=do
        s<-genHandler (\x->putStrLn $ "catch "++(show x))
        res<- install 2 s
        putStrLn $ show res
        s<-getLine

上面的代码是我想做的,只需导入signal函数,并使用haskell回调。

答案 1 :(得分:4)

晚会,但我写了一个可以提供帮助的图书馆。它允许在Windows和Linux上进行信号处理。它可以用于hackage: https://hackage.haskell.org/package/signal

答案 2 :(得分:3)

我不是Windows专家,所以我不知道你需要做什么来忽略你在这里忽略的任何事件。您可能希望在Win32文档中找到已安装的版本。但是,我对构建系统以及如何获得要构建的函数的两个版本之一了解了一下。所以策略将如下所示:

  1. 制作两个目录unix-srcWin32-src(或一些类似名称)。
  2. 在每个目录中,放置一个包含以下内容的模块OSCompat(或类似的名称):

    -- unix-src/OSCompat.hs
    module OSCompat where
    import System.Posix
    ignorePipe = installHandler sigPIPE Ignore Nothing
    
    -- Win32-src/OSCompat.hs
    module OSCompat where
    import System.Win32
    ignorePipe = -- ???
    
  3. 在您的project.cabal文件中,在executable块中输入以下内容:

    if os(windows)
        build-depends: Win32
        hs-source-dirs: Win32-src
    else
        build-depends: unix
        hs-source-dirs: unix-src
    
  4. 将您的顶级模块更改为:

    import OSCompat
    main = withSocketsDo (ignorePipe >> main')
    

答案 3 :(得分:1)

我不认为你可以在Windows上做类似的事情。 Windows不与Posix兼容,因此它不支持完整范围的信号,例如它does not support向其他进程发送信号。还有可用信号的数量is pretty limited

如果我理解正确的话,你忽略了SIGPIPE以保护你的程序不被退出,如果它的输出通过管道输送到另一个进程然后该进程终止,对吧?对不起,我不知道如何在Windows中执行此操作(事实上,您通常不会看到程序通过Windows上的简单管道进行通信)。 如果您的信号处理与套接字相关联,this可能有所帮助。