Http 从特定函数调用Haskell System.Timeout.Timeout时崩溃

Http 从特定函数调用Haskell System.Timeout.Timeout时崩溃,http,haskell,crash,timeout,io,Http,Haskell,Crash,Timeout,Io,我正在从网站域名列表的首页上抓取一些数据。他们中的一些人没有回答,或者速度非常慢,导致铲运机停止 我想通过使用超时来解决这个问题。各种可用的HTTP库似乎不支持这一点,但System.Timeout.Timeout似乎可以满足我的需要 事实上,当我测试刮取函数时,它似乎工作得很好,但当我运行封闭函数时,它就崩溃了:(为糟糕/难看的代码感到抱歉。我正在学习。) fetchPage域= --尝试从磁盘读取文件。 抓住 (System.IO.Strict.readFile$“页面缓存/”++域) (\

我正在从网站域名列表的首页上抓取一些数据。他们中的一些人没有回答,或者速度非常慢,导致铲运机停止

我想通过使用超时来解决这个问题。各种可用的HTTP库似乎不支持这一点,但System.Timeout.Timeout似乎可以满足我的需要

事实上,当我测试刮取函数时,它似乎工作得很好,但当我运行封闭函数时,它就崩溃了:(为糟糕/难看的代码感到抱歉。我正在学习。)

fetchPage域=
--尝试从磁盘读取文件。
抓住
(System.IO.Strict.readFile$“页面缓存/”++域)
(\e->下载和缓存页面域)
downloadAndCachePage域=
抓住
(做
--失败,请尝试下载它。
--当由fetchPage调用时,它会崩溃,但当从直接调用时,它可以正常工作。
可能是页面>=getResponseBody)
让page=fromMaybe“maybePage
--这主要起作用,但如果域速度慢,则不会超时。(lswb.com.cn)
--第>=getResponseBody页)
--缓存它。
writeFile(“页面缓存/”++域)页面
返回页)
(\e->catch
(做
--失败了,所以只需fuggeddaboudit。
写文件(“页面缓存/“++域)”
返回“”)
(\e->return“”)--失败太大了,所以别废话。
当从repl调用downloadAndCachePage时,超时可以正常工作,但fetchPage崩溃。如果我从downloadAndCachePage中删除超时,fetchPage将工作


任何能够解释这一点的人,或者知道其他解决方案的人?

fetchPage中的catch处理程序看起来是错误的——似乎您正试图读取一个文件,而在file not found exception中,您正从异常处理程序直接调用http函数。不要这样做。我记得,由于复杂的原因,异常处理程序中的代码并不总是像普通代码那样工作——特别是当它试图自己处理异常时。事实上,在幕后,timeout使用异步异常终止线程

一般来说,您应该在异常处理程序中放入尽可能少的代码,尤其是不要放入试图处理更多异常的代码(尽管通常可以重新释放已处理的异常以“传递它”[如
括号中的
])


这样说,即使你没有做正确的事情,崩溃(如果它是一个分段故障类型,而不是一个<代码> <代码>类型崩溃),即使从奇怪的代码,几乎总是错误的行为从GHC,如果你在GHC 7,那么你应该考虑报告这一点。您可能想考虑卷曲包与它的无数选择更多的重量级爬行:。Dons的下载curl包也为它提供了一个很好的包装器:>似乎您正在尝试读取一个文件,并且(…)从异常处理程序调用http函数。-确切地我想从磁盘读取缓存的页面(如果存在),而不是每次下载它。我将重新构造代码,使其不(ab)使用异常。

    fetchPage domain =
      -- Try to read the file from disk.
      catch
        (System.IO.Strict.readFile $ "page cache/" ++ domain)
        (\e -> downloadAndCachePage domain)


    downloadAndCachePage domain =
      catch
        (do
          -- Failed, so try to download it.

    -- This craches when called by fetchPage, but works fine when called from directly.
          maybePage <- timeout 5000000 (simpleHTTP (getRequest ("http://www." ++ domain)) >>= getResponseBody)
          let page = fromMaybe "" maybePage

    -- This mostly works, but wont timeout if the domain is slow. (lswb.com.cn)
    --      page <- (simpleHTTP (getRequest ("http://www." ++ domain)) >>= getResponseBody)

          -- Cache it.
          writeFile ("page cache/" ++ domain) page
          return page)
        (\e -> catch
          (do
            -- Failed, so just fuggeddaboudit.
            writeFile ("page cache/" ++ domain) ""
            return "")
          (\e -> return "")) -- Failed BIG, so just don't give a crap.