进程终止后释放共享内存信号量

时间:2019-03-27 08:24:06

标签: python linux ipc semaphore filelock

我有一个简短的python脚本,应该:

  • 被许多用户和线程同时使用
  • 调用另一个程序(/usr/bin/ld
  • 同时调用该另一个程序不超过x次(例如,对ld进行2次并行调用)
  • 手柄被打断/杀死

我设法使用python模块posix_ipc的共享信号量实现了大部分功能。它处理SIGTERMctrl+c-信号量已释放,但不处理SIGKILL-信号量保持获取状态,需要手动重置。这意味着对它执行两次kill -9会永久禁用它(直到应用了手动修复)。

脚本被杀死后如何释放信号量?如果不可能-是否有其他方法可以达到相似的结果?

我研究了文件锁定(假设并发使用的次数始终为2)-也许我可以拥有2个文件,尝试锁定1,如果失败则锁定另一个,然后等到可用。但是我不知道该怎么做“尝试锁定,如果其他人已经锁定了它,请再做其他事情”。

脚本的完整代码:

#!/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()

0 个答案:

没有答案