How to terminate a multi-threaded program using Ctrl + C in Python

Source: Internet
Author: User
Tags exit in

Copy codeThe Code is as follows :#! /Bin/env python
#-*-Coding: UTF-8 -*-
# Filename: peartest. py

Import threading, signal

Is_exit = False

Def doStress (I, cc ):
Global is_exit
Idx = I
While not is_exit:
If (idx <10000000 ):
Print "thread [% d]: idx = % d" % (I, idx)
Idx = idx + cc
Else:
Break
Print "thread [% d] complete." % I

Def handler (signum, frame ):
Global is_exit
Is_exit = True
Print "receive a signal % d, is_exit = % d" % (signum, is_exit)

If _ name _ = "_ main __":
Signal. signal (signal. SIGINT, handler)
Signal. signal (signal. SIGTERM, handler)
Cc = 5
For I in range (cc ):
T = threading. Thread (target = doStress, args = (I, cc ))
T. start ()

The above is a simulation program that does not actually send requests to the service. Instead, each thread prints an integer at intervals of concurrency (cc) within 10 million. Obviously, the process Exits normally after all threads complete their own tasks. But if we want to quit (imagine a stress test program that has already found a problem in the middle, and we need to stop the test), should we do it? Of course you can use ps to find the process number and kill-9 to kill it, but this is too cumbersome. Capturing Ctrl + C is the most natural idea. The above sample program has captured this signal and modified the global variable is_exit. The thread will detect this variable and exit in time.

But in fact this program does not work. When you press Ctrl + C, the program runs as usual without any response. I found some information on the Internet and found that if the python sub-thread is not daemon, the main thread cannot respond to any interruptions. But after daemon is set, the main thread will exit, and the entire process will soon exit. Therefore, you need to check the status of each sub-thread in the main thread, it does not exit until all sub-threads exit. Therefore, the code after 29 lines in the preceding example can be modified:

Copy codeThe Code is as follows: threads = []
For I in range (cc ):
T = threading. Thread (target = doStress, args = (I, cc ))
T. setDaemon (True)
Threads. append (t)
T. start ()
For I in range (cc ):
Threads [I]. join ()

Try again, the problem persists, and the process still does not respond to Ctrl + C, because the join () function will also waiting in a lock, so that the main thread cannot capture the signal. Therefore, to continue modification, call the isAlive () function of the thread to determine whether the thread is complete:

Copy codeThe Code is as follows: while 1:
Alive = False
For I in range (cc ):
Alive = alive or threads [I]. isAlive ()
If not alive:
Break

After this modification, the program runs as expected: You can print all the numbers that each thread should print, or use Ctrl + C to terminate the entire process. The complete code is as follows:

Copy codeThe Code is as follows :#! /Bin/env python
#-*-Coding: UTF-8 -*-
# Filename: peartest. py

Import threading, signal

Is_exit = False

Def doStress (I, cc ):
Global is_exit
Idx = I
While not is_exit:
If (idx <10000000 ):
Print "thread [% d]: idx = % d" % (I, idx)
Idx = idx + cc
Else:
Break
If is_exit:
Print "receive a signal to exit, thread [% d] stop." % I
Else:
Print "thread [% d] complete." % I

Def handler (signum, frame ):
Global is_exit
Is_exit = True
Print "receive a signal % d, is_exit = % d" % (signum, is_exit)

If _ name _ = "_ main __":
Signal. signal (signal. SIGINT, handler)
Signal. signal (signal. SIGTERM, handler)
Cc = 5
Threads = []
For I in range (cc ):
T = threading. Thread (target = doStress, args = (I, cc ))
T. setDaemon (True)
Threads. append (t)
T. start ()
While 1:
Alive = False
For I in range (cc ):
Alive = alive or threads [I]. isAlive ()
If not alive:
Break

In fact, this is also required if you use python to write a service, because the thread in charge of the Service will always receive requests there and will not exit, if you want to use Ctrl + C to kill the entire service, keep up with the stress testing program above. To sum up, in python multithreading, to respond to the Ctrl + C signal to kill the entire process, you need:

1. Set all sub-threads as Daemon;
2. Use the isAlive () function to determine whether all sub-threads are completed, rather than waiting for completion using the join () function in the main thread;
3. Write a function that responds to the Ctrl + C signal and modify the global variables so that the sub-threads can detect and exit normally.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.