Можно ли предотвратить взлом SIGINT для раздела кода? - PullRequest
0 голосов
/ 15 января 2020

Я работаю со скриптом python, который записывает в файл несколько длинных sh строк текста. Для дальнейшей обработки важно, чтобы эти строки были либо полностью написаны, либо пропущены полностью. Откладывая в сторону возможные сбои, которые вряд ли могут сделать их достойными особого внимания в коде, я хотел бы сделать раздел записи «atomi c» * относительно сигналов SIGINT, чтобы, если мне нужно было остановить программу на в любой точке с помощью Ctrl + C у меня не будет частично написанных строк в файле.

Я нашел этот ответ , который заменяет обработчик сигнала. Я думал, что мог бы установить временный обработчик сигнала в начале «критической секции» (например, до file.write(my_long_text_line)) и восстановить исходную в конце (плюс некоторую бухгалтерию для обработки SIGINT, полученных в критической секции), но это было бы много перестановочных обработчиков, поэтому мне было интересно, есть ли лучший способ добиться этого.


*: "atomi c", означающий "Если я отправлю SIGINT, находясь внутри этого раздела, сигнал будет обработан после завершения раздела кода ", меня не интересуют проблемы, связанные с параллелизмом.

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Вам не нужно устанавливать другой обработчик для SIGINT каждый раз, когда вы пишете. Блокировки и разблокировки SIGINT вокруг критического раздела должно быть достаточно.

Ниже показано, как этого добиться.

Обратите внимание, что после разблокировки SIGINT он будет доставлен процессу, если он был получен во время критической секции, т.е. когда он был заблокирован. Если было получено несколько SIGINT сигналов, только один будет доставлен после разблокировки.

#!/usr/bin/python3.6
import os
import signal
import time

def do_something(line):
    try:
        signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])
        # Critical section
        #
        # Uncomment the following 2 lines to verify that SIGINT is indeed blocked
        # print("Waiting in the critical section...")
        # time.sleep(30)
        print("Signal SIGINT is blocked here: " + line)
    finally:
        signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])

def main():
    print("start")
    do_something("some line")
    print("done")

if __name__ == "__main__":
    main()
0 голосов
/ 15 января 2020

Для простого, грязного решения:

try:
    do_your_stuff()
except KeyboardInterrupt:
    do_closing_action()

Я бы предложил использовать счетчик для отслеживания текущей записываемой строки, затем при Ctrl- C проверьте, была ли написана строка, напишите если нет, то звоните exit()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...