Как остановить все запущенные потоки в Python при сбое? - PullRequest
0 голосов
/ 08 июня 2018

В настоящее время я работаю над скриптом Python 3, который предназначен для стресс-тестирования службы ARP.В настоящее время я создаю до 255 «рабочих» потоков, а затем отправляю до 2 ^ 15 пакетов для стресс-тестирования сервера.Это основной тестовый скрипт, который я запускаю:

if __name__ == '__main__':
    for i in range(0, 8):
        for j in range(0, 15):
            print("Multithreading test with", 2**i, "workers and ", 2**j,
                  "packets:")
            sleep(3)
            try:
                arp_load_test.__main__(2**i)
            except:
                print("Multithreading test failed at", 2**i, "workers and ",
                      2**j, "packets:")
                break

    print("Moving on to the multiprocessing test.")
    sleep(10)

    for i in range(0, 15):
        print("Multiprocessing test with", 2**i, "workers:")
        sleep(3)
        try:
            arp_load_test2.__main__(2**i)
        except:
            print("Multiprocessing test failed at", 2**i, "workers.")
            print("\n\n\t\t\t\tDONE!")
            break

Первый блок кода проверяет многопоточность, а второй выполняет то же самое, за исключением многопроцессорной обработки.arp_load_test.py - это многопоточная версия многопроцессорной обработки arp_load_test2.py.В части except каждого из циклов for я хочу завершить цикл, как только один из потоков выйдет из строя.Как я могу это сделать?Вот код для arp_load_test.py, и arp_load_test2.py - почти то же самое:

def __main__(threaders = 10, items = 10):
    print("\tStarting threading main method\n")
    sleep(1)
    a = datetime.datetime.now()
    # create a logger object
    logging.basicConfig(filename = "arp_multithreading_log.txt",
                        format = "%(asctime)s %(message)s",
                        level = logging.INFO)

    # default values
    interface = "enp0s8"
    workers = threaders
    packets = items
    dstip = "192.168.30.1"
    # parse the command line
    try:
        opts, args = getopt.getopt(sys.argv[1:], "i:w:n:d:", ["interface=",
                                                              "workers=",
                                                              "packets=",
                                                              "dstip="])
    except getopt.GetoptError as err:
        print("Error: ", str(err), file = sys.stderr)
        sys.exit(-1)
    # override defaults with the options passed in on the command line
    for o, a in opts:
        if o in ("-i", "--interface"):
            interface = a
        elif o in ("-w", "--workers"):
            w = int(a)
            if w > 254:
                workers = 254
                print("Max worker threads is 254. Using 254 workers",
                      file = sys.stderr)
            elif w < 1:
                workers = 1
                print("Min worker threads is 1. Using 1 worker",
                      file = sys.stderr)
            else:
                workers = w
        elif o in ("-n", "--packets"):
            packets = int(a)
        elif o in ("-d", "--dstip"):
            dstip = a
        else:
            assert False, "unhandled option"
    # create an empty list as a thread pool
    office = []
    # give all the workers jobs in the office
    for i in range(workers):
        office.append(ArpTestThread(i, "ARP-" + str(i), i, interface, packets,
                                    dstip))

    # do all the work
    logging.info("BEGIN ARP FLOOD TEST")
    for worker in office:
        worker.daemon = True
        worker.start()
    for worker in office:
        worker.join()

    b = datetime.datetime.now()
    print("\tSent", len(office) * packets, "packets!\n")
    print("It took", a - b, "seconds!")
    logging.info("END ARP FLOOD TEST\n")
    sleep(5)
    ##### end __main__

ArpTestThread - это дочерний объект threading.Thread (или Process), который настроен наотправить пакеты в службу ARP.Кроме того, я запускаю тестовый скрипт изнутри виртуальной машины через Терминал, но я не использую какие-либо параметры командной строки, для которых настроена программа, я просто добавил параметры вместо b / c lazy.


Нужно ли помещать try block внутри файла класса вместо тестового скрипта?Мне дали 90% кода файла класса, который уже готов, и я обновляю его и пытаюсь собрать данные о том, что он делает, а также оптимизировать его, чтобы должным образом подчеркнуть службу ARP.Я хочу, чтобы циклы for в тестовом скрипте (самая первая часть кода в этом посте) прерывались, останавливали все запущенные в данный момент потоки и распечатывали, в какой момент программа завершилась неудачей, как только один из потоков / процессов завершится сбоем,Это возможно?


РЕДАКТИРОВАТЬ: Предложенный дубликат вопрос не решает мою проблему.Я пытаюсь отправить пакеты, и это не вызывает исключение, пока программе по существу не хватает памяти для продолжения отправки пакетов в службу ARP.Я не получаю исключения, пока сама программа не сломается, поэтому возможное решение, которое предполагает использование простого сигнала, не работает.

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

...