5

I would like to exit the program gracefully on Ctrl+C / SIGINT or on user input. If possible the terminal should prompt something like; "Hit enter to terminate".

Code to be executed by Python 3.6

def worker(process):
    i = 0
    while True:
        print('Process %d count %d' % (process, i))
        i += 1

def main():
    available_num_cores = multiprocessing.cpu_count()
    use_num_cores = available_num_cores - 1 if available_num_cores > 1 else 1

    print('Using %d cores' % use_num_cores)

    pool = multiprocessing.Pool(use_num_cores)

    for i in range(0, use_num_cores):
        pool.apply_async(worker, args=(i,))
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

Accepted answer for this question Catch Ctrl+C / SIGINT and exit multiprocesses gracefully in python. Isn't working, it fail with error:

Process SpawnPoolWorker-1:
Process 0 count 1572
Process SpawnPoolWorker-2:
Process 1 count 1472
Process SpawnPoolWorker-3:
Traceback (most recent call last):

Any help would be appreciated. Thanks!

Mikael
  • 5,429
  • 5
  • 30
  • 38
  • I updated the question. Also I'm looking for a solution that support input by user and not only ctrl+c – Mikael Jun 27 '17 at 12:21

1 Answers1

1

You need to make sure the SIGINT is ignored by the children processes.

Then you just either wait for user input or for a CTRL+C to be issued.

def initializer():
    """Ignore SIGINT in child workers."""
    signal.signal(signal.SIGINT, signal.SIG_IGN)


def main():
    try:
        pool = multiprocessing.Pool(use_num_cores, initializer=initializer)

        for i in range(0, use_num_cores):
            pool.apply_async(worker, args=(i,))

        pool.close()

        input("Hit enter to terminate")
    except KeyboardInterrupt:
        print("CTRL+C")
    finally:
        pool.terminate()
        pool.join()        

        print("Bye have a great time!")
noxdafox
  • 14,439
  • 4
  • 33
  • 45
  • This works for input but not for CTRL+C. Seems like input() block KeyboardInterrupt. "CTRL+C" is printed after one hit enter, even though CTRL+C was executed first. – Mikael Jun 27 '17 at 14:15
  • I just tried the code and it works flawlessly. Are you sure you are setting the signal handler correctly? – noxdafox Jun 27 '17 at 15:47
  • It seems to behave differently on OS X and Win10. Tested on both and it fails on Win10 but works on OS X. Any ideas? – Mikael Jun 27 '17 at 18:39
  • The bug https://bugs.python.org/issue26531 links to some stackoverflow issue which explains how to overcome the issue: https://stackoverflow.com/questions/31127652/cannot-catch-keyboardinterrupt-in-command-prompt-twice – noxdafox Jun 27 '17 at 18:56