gpt4 book ai didi

linux - forkIO/killThread 与 forkProcess 的交互

转载 作者:太空狗 更新时间:2023-10-29 11:09:15 25 4
gpt4 key购买 nike

我已经编写了下面的代码,并注意到 killThread 阻塞并且线程仍在继续。只有当我在 forkProcess 中执行此操作时才会发生这种情况,如果我删除 forkProcess,一切都会按预期进行。

代码

{-# 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

输出

$ 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 64bit 上运行这个。

最佳答案

bug report注意到 forkProcess 屏蔽了子进程中的异步异常,尽管文档中没有这样的指示。该行为应在 7.8.1 发布时修复。

当然,如果屏蔽了异步异常,killThread里面的throw就会无限阻塞。如果您简单地删除 main 中包含 forkProcessgetProcessStatus 的行,程序将按预期运行:

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 中手动取消屏蔽子进程中的异步异常。

关于linux - forkIO/killThread 与 forkProcess 的交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22052575/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com