5

In this script:

import threading, socket    

class send(threading.Thread):

    def run(self):
        try:
            while True:
                try:
                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    s.connect((url,port))
                    s.send(b"Hello world!")
                    print ("Request Sent!")
                except:
                    s.close()
        except KeyboardInterrupt:
            # here i'd like to kill all threads if possible

for x in range(800):
    send().start()  

Is it possible to kill all threads in the except of KeyboardInterrupt? I've searched on the net and yeah, I know that it has been already asked, but I'm really new in python and I didn't get so well the method of these other question asked on stack.

Allexj
  • 1,375
  • 6
  • 14
  • 29
  • 1
    You want to kill all threads... does this include the main thread and as a consequence, the application? If so, simply make all your threads [daemons](https://docs.python.org/3.4/library/threading.html#threading.Thread.daemon) and then when you want to quit, use `sys.exit()`. – CristiFati Sep 08 '16 at 00:32
  • @CristiFati: That won't help if the `KeyboardInterrupt` is delivered to one of the threads (the thread that receives it is basically random IIRC). Thus the need for alerting the main thread so it can `exit` at the appropriate time. – ShadowRanger Sep 08 '16 at 00:34
  • Right @ShadowRanger, thank you for pointing it out, threads tend to swallow exceptions. As a note, when I'm dealing with threads, I use the reverse approach: in a thread's loop, if a key was pressed (the logic can be expanded based on key), end it. – CristiFati Sep 08 '16 at 00:45
  • No way ! Socket is external thread. Set a timeout value for auto kill. How to handle `*socket.error`? `while True` is bad idea, `while some_status_bolean` better ! – dsgdfg Sep 08 '16 at 07:56

3 Answers3

4

No. Individual threads can't be terminated forcibly (it's unsafe, since it could leave locks held, leading to deadlocks, among other things).

Two ways to do something like this would be to either:

  1. Have all threads launched as daemon threads, with the main thread waiting on an Event/Condition and exiting as soon as one of the threads sets the Event or notifies the Condition. The process terminates as soon as the (sole) non-daemon thread exits, ending all the daemon threads
  2. Use a shared Event that all the threads poll intermittently, so they cooperatively exit shortly after it is set.
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • thanks for answer. I've seen the 2 way here: http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python but I really don't know how to implement it to my send() class. – Allexj Sep 08 '16 at 00:58
  • I'm running on Linux – Allexj Sep 08 '16 at 10:38
  • so? anyone can help me or it's impossible to add a killing thread in keybord interrupt? – Allexj Sep 09 '16 at 09:34
  • 1
    @allexj: You can't kill threads, like I already said. Use a shared `Event`, change `while True:` to `while not myevent.is_set():`, and stop using a bare `except` inside the loop (it will catch `KeyboardInterrupt` preventing you from processing it; catch `Exception` or the like). Then when you catch `KeyboardInterrupt`, call `myevent.set()` to tell all the other threads to stop processing on their next loop. This is not that hard to adapt, try playing around with it if it doesn't work immediately. – ShadowRanger Sep 09 '16 at 10:47
0

As a comment said, use exit(n) to terminate a threads, but it might not terminate all threads necessarily and threads will mostly continue to run.

So your approach is to use os._exit(n), This terminates all threads and does what you want.

But be warned os._exit is not a good way to exit a script, and should be used only in special cases.

WarnerStark
  • 172
  • 11
0

@Allexj: You got an accurate answer from @ShadowRanger. You can do it as shown below.

import threading, socket, sys

event = Threading.Event()   # define an Event

class send(threading.Thread):

    def run(self):
        try:
            global event
            while True:
                try:
                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    s.connect((url,port))
                    s.send(b"Hello world!")
                    print ("Request Sent!")
                except:
                    s.close()
        except KeyboardInterrupt:
            # here i'd like to kill all threads if possible
            event.set()  # set the event as soon as any thread receives an keyboardInterrupt.

try:
    for x in range(800):
        send(daemon=True).start()
    event.wait()
except KeyboardInterrupt:  # If user pressed ctrl+c while loop was still running, then this will be useful
    pass
sys.exit(0)
Bhavesh Achhada
  • 101
  • 1
  • 9