Освободить семафор разделяемой памяти, когда процесс убит - PullRequest
0 голосов
/ 27 марта 2019

У меня есть короткий скрипт на python, который должен:

  • может использоваться многими пользователями и потоками одновременно,
  • вызов другой программы (/usr/bin/ld)
  • вызывайте эту другую программу не более x раз одновременно (например, 2 одновременных вызова ld)
  • ручка прерывается / убивается

Мне удалось добиться большей части этого, используя общий семафор из модуля Python posix_ipc . Он обрабатывает SIGTERM и ctrl+c - семафор освобожден, но он не обрабатывает SIGKILL - семафор остается полученным и должен быть сброшен вручную. Это означает, что выполнение kill -9 дважды отключает его навсегда (пока не будет применено ручное исправление).

Как освободить семафор, когда скрипт убит? Если не возможно - есть ли другой метод для достижения аналогичного результата?

Я изучил блокировки файлов (предполагая, что число одновременных использований всегда будет равно 2) - возможно, у меня может быть 2 файла, попробуйте заблокировать 1, если не удалось заблокировать другой, и подождите, пока не станет доступным. Но я не мог понять, как сделать «попытаться заблокировать, если sb else уже заблокировал его, сделайте что-то еще».

Полный код скрипта:

#!/usr/bin/env python3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
# -*- coding: utf-8 -*-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

import posix_ipc                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
import subprocess                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
import sys                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
import signal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

SEM_NAME = '/serialize_ld'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
MAX_CONCURRENT = 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PROGRAM = '/usr/bin/ld'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            


def main():                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    import os                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    os.umask(0)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    sem = posix_ipc.Semaphore(SEM_NAME, posix_ipc.O_CREAT, mode=0o666, initial_value=MAX_CONCURRENT)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
    sem.acquire()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

    def release_semaphore(signum, frame):                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        print("exiting due to signal " + str(signum))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        sem.release()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        sem.close()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        sys.exit(1)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    signal.signal(signal.SIGTERM | signal.SIGINT | signal.SIGKILL, release_semaphore)                                                                                                                                                                                                                                                                                                                                                                                                                                                              

    try:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        subprocess.call([PROGRAM, *sys.argv[1:]])                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    finally:
        sem.release()
        sem.close()


if __name__ == "__main__":
    main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...