首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >forkIO/扑灭线程与forkProcess的交互

forkIO/扑灭线程与forkProcess的交互
EN

Stack Overflow用户
提问于 2014-02-26 20:30:54
回答 1查看 144关注 0票数 3

我编写了下面的代码,并注意到killThread块和线程仍然在继续。只有当我在forkProcess中这样做,如果我删除forkProcess,一切都按预期工作时才会发生这种情况。

代码

代码语言:javascript
复制
{-# LANGUAGE TupleSections #-}
module Main where

import Control.Concurrent
import Control.Monad
import System.Posix.Process

{-# NOINLINE primes #-}
primes :: [Integer]
primes = 2:[x | x <- [3..], all (not . flip isDivisorOf x) (takeWhile (< truncate (sqrt $ fromInteger x :: Double)) primes)]
  where x `isDivisorOf` y = y `rem` x == 0

evaluator :: Show a => [a] -> IO ()
evaluator xs = do
  putStrLn "[Evaluator] Started evaluator."
  forM_ xs $ \x -> putStrLn $ "[Evaluator] Got result: " ++ show x
  putStrLn "[Evaluator] Evaluator exited."

test :: IO ThreadId
test = forkIO (evaluator $ filter ((== 13) . flip rem (79 * 5 * 7 * 3 * 3 * 2 * 3)) primes) -- Just some computation that doesn't finsish too fast

main :: IO ()
main = do
  pid <- forkProcess $ do
    a <- test
    threadDelay $ 4000 * 1000
    putStrLn "Canceling ..."
    killThread a
    putStrLn "Canceled"
  void $ getProcessStatus True False pid

输出

代码语言:javascript
复制
$ ghc test.hs -O -fforce-recomp -threaded -eventlog -rtsopts # I also tried with -threaded
$ ./test +RTS -N2  # I also tried without -N
[Evaluator] Started evaluator.
[Evaluator] Got result: 13
[Evaluator] Got result: 149323
[Evaluator] Got result: 447943
[Evaluator] Got result: 597253
[Evaluator] Got result: 746563
[Evaluator] Got result: 1045183
Canceling ...
[Evaluator] Got result: 1194493
[Evaluator] Got result: 1642423
[Evaluator] Got result: 1791733
[Evaluator] Got result: 2090353
[Evaluator] Got result: 2687593
[Evaluator] Got result: 3135523
[Evaluator] Got result: 3284833
[Evaluator] Got result: 4777933
[Evaluator] Got result: 5375173
^C[Evaluator] Got result: 5524483
^C

这不是通常的问题,没有内存分配,因此GHC的线程调度程序不运行。我通过使用+RTS -sstderr运行程序来验证这一点,这表明垃圾收集器经常运行。我正在linux 64位上运行这个程序。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-26 21:04:54

错误报告注意到,尽管文档中没有显示异步异常,但forkProcess掩盖了子进程中的异步异常。发布时,行为应该在7.8.1中修正。

当然,如果异步异常被屏蔽,killThread中的killThread将无限期地阻塞。如果您只需删除main中包含forkProcessgetProcessStatus的行,程序将按预期工作:

代码语言:javascript
复制
module Main where

import           Control.Concurrent
import           Control.Monad
import           System.Posix.Process

{-# NOINLINE primes #-}
primes :: [Integer]
primes = 2:[ x | x <- [3..], all (not . flip isDivisorOf x) (takeWhile (< truncate (sqrt $ fromInteger x :: Double)) primes)]
  where x `isDivisorOf` y = y `rem` x == 0

evaluator :: Show a => [a] -> IO ()
evaluator = mapM_ $ \x ->
  putStrLn $ "[Evaluator] Got result: " ++ show x

test :: IO ThreadId
test = forkIO (evaluator $ filter ((== 13) . flip rem (79 * 5 * 7 * 3 * 3 * 2 * 3)) primes) -- Just some computation that doesn't finsish too fast

main :: IO ()
main = do
  a <- test
  threadDelay $ 4000 * 1000
  putStrLn "Canceling ..."
  killThread a
  putStrLn "Canceled"

我用ghc --make -threaded async.hs构建它,并使用./async +RTS -N4运行它。

如果由于某种原因需要单独的进程,则必须手动解除GHC 7.6.3中子进程中的异步异常。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22052575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档