Почему signal.pause () не дает сокетам сломаться? - PullRequest
0 голосов
/ 13 июня 2018

Я работаю с сокетами, используя Python 3.5 и модуль multiprocessing, и столкнулся с неожиданным поведением.Моя программа, по сути, состоит из пары потоков, которые выполняются до тех пор, пока клиент не получит определенное сообщение с указанием остановить его.

Если я выполню его таким образом, я получу BrokenPipeError, который прерывает программу, несмотря на *Цикл 1005 * и блок except.

#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process

def main():
    while True:
        try:
            # a Process has a couple threads
            process = Process()
            listener_pool = Pool(processes=1)
            sender_pool = Pool(processes=1)

            # blocking socket client that runs forever
            listener_pool.apply_async(process.listener_thread.run, ())

            # blocking socket server that runs forever
            sender_pool.apply_async(process.sender_thread.run, ())

            return 0

        except BrokenPipeError:
            traceback.print_exc()

            # closing connections
            process.emitter_thread.socket.close()
            process.listener_thread.socket.close()

if __name__ == '__main__':
    main()

Однако, когда я добавил signal.pause() прямо перед возвратом, не только код работает, как задумано, но также не вызывается BrokenPipeError в любомвремя.

#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process

def main():
    while True:
        try:
            # a Process has a couple threads
            process = Process()
            listener_pool = Pool(processes=1)
            sender_pool = Pool(processes=1)

            # blocking socket client that runs forever
            listener_pool.apply_async(process.listener_thread.run, ())

            # blocking socket server that runs forever
            sender_pool.apply_async(process.sender_thread.run, ())
            signal.pause()
            return 0

        except BrokenPipeError:
            traceback.print_exc()

            # closing connections
            process.emitter_thread.socket.close()
            process.listener_thread.socket.close()


if __name__ == '__main__':
    main()

В соответствии с документами сигналы могут обрабатываться только основным потоком, но оба сокета обрабатываются вторичными потоками.Что делает signal.pause(), чтобы предотвратить разрыв сокетов, когда они даже не вызываются в одном и том же контексте?

1 Ответ

0 голосов
/ 13 июня 2018

apply_async, как следует из названия, возвращается немедленно.Таким образом, в первой версии вашей программы основной поток завершает работу сразу после запуска дочерних потоков (фиктивные процессы - это просто потоки, использующие многопроцессорный API ).

Поэтому основной поток завершилсяблок try задолго до возникновения исключения.

Во втором случае signal.pause() заставляет главный поток ждать в блоке try, где он будет перехватывать исключение.

Обратите внимание, что это хрупкое решение, так как получение любого сигнала приведет к возобновлению signal.pause() и выходу основного потока.

...