1

Duplicate of How to prevent a block of code from being interrupted by KeyboardInterrupt in Python?

Purpose:

  • When program receives a signal, it exits only when it is ready.

Problem:

  • Desired behavior:
    • Signal arrives during target block. Program exits after target block finishes.
    • Signal arrives outside target block. Program exits.
  • Current behavior:
    • Signal arrives during target block. Program hangs.
    • Signal arrives outside target block. Program exits.

 

Generic implementation of my design:

import threading, signal

def huphandler(signum, frame):
    with sig_lock:
        os._exit(0)

def loop():
    print 'in lock'
    time.sleep(5)

def idle_loop():
    while True:
        with sig_lock:
            t = multiprocessing.Process(target=loop)
            t.start()
            t.join()
        print 'out lock'
        time.sleep(5)

sig_lock = threading.Lock()
signal.signal(signal.SIGHUP, huphandler)
idle_loop()
Community
  • 1
  • 1
user193661
  • 879
  • 10
  • 29

2 Answers2

0

If you kill with the lock acquired then you put your program in a deadlock state.

Because you just killed the thread or subprocess that holds the lock, it can no longer release it. Then your main thread, or any other thread, will try to acquire the lock, and block until the lock is available. Thus, ending in a deadlock.

The Brofessor
  • 1,008
  • 6
  • 15
0

1.1. Problem:

  • The signal handler will interrupt the main thread, causing deadlock.

1.2. Solution:

  • Use a boolean instead of a lock.

2.1. Problem:

  • When a thread is interrupted, it may cease mid-operation (i.e., time.sleep) which is unstable.

2.2. Solution:

  • For greater stability, wrap the target code in a subprocess.

 

Generic implementation which provides desired results:

import threading, signal

def huphandler(signum, frame):
    print idle_loop.sig_lock
    if idle_loop.sig_lock:
        idle_loop.continuee = False
    else:
        print 'dont b here'
        os._exit(0)

def loop():
    print 'in lock'
    time.sleep(5)

def idle_loop():
    while True:
        idle_loop.sig_lock = True
        t = multiprocessing.Process(target=loop)
        t.start()
        t.join()
        print 'out lock'
        if idle_loop.continuee:
            idle_loop.sig_lock = False
            time.sleep(5)
        else: return


idle_loop.sig_lock = False
idle_loop.continuee = True
signal.signal(signal.SIGHUP, huphandler)
idle_loop()
user193661
  • 879
  • 10
  • 29