سؤال

لقد كتبت الرمز أدناه ، ولاحظت ذلك killThread كتل والخيط لا يزال مستمرا.يحدث هذا فقط إذا قمت بذلك في عملية الشوكة ، إذا قمت بإزالة عملية الشوكة ، فكل شيء يعمل كما هو متوقع.

كود

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

هذه ليست المشكلة المعتادة أنه لا يوجد تخصيص الذاكرة وبالتالي لا يتم تشغيل جدولة مؤشر ترابط غك.لقد تحققت من ذلك عن طريق تشغيل البرنامج مع +RTS -sstderr, ، مما يدل على أن جامع القمامة يعمل كثيرا.أنا تشغيل هذا على لينكس 64 بت.

هل كانت مفيدة؟

المحلول

هذا تقرير الأخطاء تلاحظ أن forkProcess أقنعة الاستثناءات غير المتزامنة في عملية الطفل على الرغم من عدم وجود إشارة إلى ذلك في الوثائق.يجب إصلاح السلوك في 7.8.1 عند إصداره.

بالطبع ، إذا تم إخفاء الاستثناءات غير المتزامنة ، فإن throw داخل killThread سوف تمنع إلى أجل غير مسمى.إذا قمت ببساطة بحذف الأسطر في main تحتوي على forkProcess و getProcessStatus, ، يعمل البرنامج على النحو المنشود:

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.

إذا لسبب ما كنت بحاجة إلى عملية منفصلة ، سيكون لديك لكشف يدويا الاستثناءات غير المتزامنة في عملية الطفل في غك 7.6.3.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top