On Thu, 27 Jun 2019 at 20:53, Yonatan Zunger <zun...@humu.com> wrote:
> 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?) > That's precisely why thread cancellation in managed languages (like Python is) raise an exception to terminate the the thread and honour finally blocks. > 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. > This is not what is being suggested. Read about the semantics of thread killing in C# and Java. > 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: > Yet again someone who doesn't understand what is being proposed saying it isn't needed. Michael > (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 <fuzzy...@gmail.com> wrote: > >> >> >> On Thu, 20 Jun 2019 at 16:33, Guido van Rossum <gu...@python.org> wrote: >> >>> On Thu, Jun 20, 2019 at 8:21 AM Michael Foord <fuzzy...@gmail.com> >>> 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?view=netframework-4.8 >> >> 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-le...@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/ARIZ3WMWXIP6MICQFW3OKE4VY43OKXEK/ > > >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > -- 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-le...@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/PB5SX3BRODO5TYK63RBETXOF4CJCGPPF/ Code of Conduct: http://python.org/psf/codeofconduct/