Как убить нить в Haskell

Используя Control.Concurrent и forkIO, есть некоторые случаи, которые оставят поток в заблокированном состоянии (это особенно часто встречается в Windows с сетью), поэтому, даже если вы пытаетесь использовать killThread, исключение никогда не возникает в потоке.  Есть ли другой способ заставить поток умереть?

Моя попытка прекратить все приложение с помощью exitFailure из вспомогательного потока не имеет никакого эффекта в этих условиях.

Славная система компиляции Haskell Glasgow, версия 6.12.1 HP 2010.1.0.0

EDIT: Чтобы очистить все, я не хочу прекращать приложение, я бы предпочел просто убить поток, который был заблокирован в течение очень долгого времени. Однако существует множество примеров даже здесь, в SO с полным кодом, используя exitWith в вспомогательном потоке, и такая схема не работает в условиях, которые у меня есть.

Ответ 1

Чтобы развернуть мой комментарий выше, вы не можете прервать блокировку внешних вызовов. Однако вы можете использовать неблокирующий IO. В случае пакета Network это означает recvLen для строк и recvFrom для байтов. Я предполагаю, что вы всегда указываете также время выполнения потока?

Ответ 2

Еще одна вещь, которую следует отметить, заключается в том, что программы GHC завершаются, когда основной поток завершается. Жизнеспособность дочерних потоков неважно. Если вы создаете свое приложение таким образом, чтобы всегда можно было сигнализировать основному потоку, что его время заканчивается, не имеет значения, как заблокированы любые дочерние потоки.

Ответ 3

В средах Posix вы можете завершить весь процесс:

-- | @'exitImmediately' [email protected] calls @[email protected] to terminate the process
--   with the indicated exit @[email protected]
--   The operation never returns.
exitImmediately :: ExitCode -> IO ()

Из пакет unix. В пакете Win32 может быть аналогичная функция, отличная от Posix.

Однако лучше спроектировать ваше приложение таким образом, чтобы ваши сигнальные механизмы соблюдались, конечно.

Ответ 4

Вы можете вызвать API ExitProcess() из любого потока вашего приложения, а весь процесс, потоки и все, будут прекращены. Есть некоторые проблемы с некоторыми отсоединениями DLL, которые могут вызвать проблему, и процесс не может быть прерван до тех пор, пока все дескрипторы для него не будут выпущены, но ExitProcess() всегда отлично работает для меня в качестве последнего средства.

ExitProcess() не заботится о том, в каком состоянии находятся ваши потоки. Может быть заблокирован при вводе-выводе или запущен на другом процессоре, чем поток, который вызывает ExitProcess() - это не имеет значения, ОС остановит их все.

Rgds, Мартин