Generally, threads don't have a notion of non-cooperative thread
termination. This is because (unlike processes) threads share address
spaces, and an unexpected termination of a thread can leave memory in
arbitrary and unexpected states. (For example, what if one thread was
holding a mutex when it got killed?)
The POSIX threading model *does* include the ability to send a signal to a
particular thread using pthread_kill(). What that does is cause the
process' globally-registered signal handler for that signal to be invoked
in that particular thread. With the default handlers, though, these tend to
have process-wide effects; e.g., if you pthread_kill(tid, 15) with the
default handler, it will simply kill the process. This doesn't make as much
sense in the context of Python's signal handling (which is a layer on top
of POSIX signal handling) so signals.pthread_kill() isn't a very useful
function.
In practice (and I actually had to deal with exactly this problem in my own
code just last week!) there are two approaches that tend to work:
(1) Cooperative scheduling: Your code has an explicit place within the
threads where they check for abort signals and handle them appropriately.
For example, if your threads are each running event listeners, you might
post a "cancel" event on the main bus; or alternately, you could use a
threading.Event to signal everyone to shut down.
(2) Separate address spaces: If (1) isn't possible for some reason, and you
need to literally be able to kill off a process noncooperatively -- say,
the purpose of your code is to be an intermediate "harness" library which
runs someone else's long-running functions in a thread, and it's not
possible to require all of that code to obey a cooperative protocol -- then
use processes instead of threads.
In many cases, you can achieve this with built-in Python libraries like
multiprocessing and ProcessPoolExecutor, and in this case, you can
terminate processes simply by calling Popen.send_signal() or the like. In a
few cases (e.g., if you're using gRPC, whose client library is incompatible
with those for complicated reasons) you'll have to fork() and exec()
yourself, typically by using the subprocess.Popen library directly.
Yonatan
On Thu, Jun 20, 2019 at 10:16 AM Michael Foord
On Thu, 20 Jun 2019 at 16:33, Guido van Rossum
wrote: On Thu, Jun 20, 2019 at 8:21 AM Michael Foord
wrote: It works by raising an exception in the target thread, which the thread is free to handle (usually for cleanup and then reraise).
Sure, those are the right semantics. How does it stop blocking I/O though? Suppose the thread is waiting for a server to return a response which just isn't ever going to come, but the connection somehow is kept open by the other side?
Sorry, resending to list as well.
It used to be on the CLR getting back control. So it couldn't handle that case. (.NET 1.1).
https://jonskeet.uk/csharp/threads/abort.html
It has since been improved. It still blocks on the execution of unmanaged code (or computation in a finally block handling the ThreadAbortException), but blocking IO can be interrupted:
https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?vi...
If Abort is called on a thread that is blocked or is sleeping, the thread is interrupted and then aborted.
This SO question on the topic says:
https://stackoverflow.com/questions/365370/proper-way-to-stop-tcplistener
Thread.Abort()
There are 2 things I see you could do. 1 is that if you have started this TcpListener thread from another you can simply call Thread.Abort instance method on the thread which will cause a threadabortexception to be thrown within the blocking call and walk up the stack.
Michael
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)
--
Michael Foord
Python Consultant, Contractor and Trainer
https://agileabstractions.com/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ARIZ3W... Code of Conduct: http://python.org/psf/codeofconduct/