Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

externally kill a thread

3 views
Skip to first unread message

yeb...@usa.net

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

Hi,

What is the safest way to kill a thread externally? There is a chance that if
the tread processing takes to long I will have to terminate it from outside
the thread. This can happen within a Winsock I/O function so I cannot just
set a flag to terminate the thread from within the thread itself.

I'd appreceate it if anybody has any ideas.

Thanks!!!

Yaakov Blank
yeb...@usa.net

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

Stephen Flynn

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

yeb...@usa.net wrote:

> What is the safest way to kill a thread externally? There is a chance that if
> the tread processing takes to long I will have to terminate it from outside
> the thread. This can happen within a Winsock I/O function so I cannot just
> set a flag to terminate the thread from within the thread itself.

What do you mean by safest? I prefer the binary model when it comes to thread
termination: safe or unsafe. I am not as familiar with the Win32 threading model
as the POSIX model.
TerminateThread() is definitely unsafe.

Allow me to give you a circuitous but, I hope, meaningful reply.

In POSIX when a thread's cancelability type is set to
PTHREAD_CANCEL_ASYNCHRONOUS, the thread can be canceled at any time, possibly in
the middle of a critical code section which does not contain a failure back-out
path. When having a asynchronous cancelability type, a thread should
not acquire any resources and should call only async-cancel-safe functions. If
this advice is not followed, the thread needs to install cancellation handlers
cleanup handlers for every resource it acquires. If cleanup handlers are not
installed, acquired resources are not released when the thread
is canceled.

In a related vein, POSIX provides cancellation points, which are the only places
a killee thread
may be canceled if its cancelablity type is PTHREAD_CANCEL_DEFERRED (the default
value
for all threads).

According to Dave Butenhof:
----------------------------------------
"POSIX doesn't have
select(), and, therefore, did not specify that it was a cancellation
point. The Single UNIX Specification, Version 2, however, (UNIX98), does
specify that select() is a cancellation point. [PROPERTY A:] Most POSIX thread
implementations will already implement select() as a cancellation point,
and any that are UNIX98 branded will be required to do so."
-------------------------------------------------------------

According to POSIX, a thread needs to process a pending cancellation point
request only if it is about to block indefinitely. This is the minimum
requirement in processing cancellation requests. PROPERTY B: Most systems cancel
the target thread if the thread is blocked indefintely inside
a function that is a cancellation point,

So, combining PROPERTY B with Butenhof's PROPERTY A, we see that if a killee
thread is
in a socket i/o system call like select(), msgrcv(), etc., it can be cancelled.
(In fact, in many implementations, if a function can return with an EINTR error,
chances are that it is a cancellation point)

I don't recall Win32 providing the functionality of PTHREAD_CANCEL_DEFERRED. So
that
leaves the functionality of PTHREAD_CANCEL_ASYNCHRONOUS.

So my question is: In Win32, (1) can a killee thread install cleanup handlers for
every resource it
acquires, and (2) is there a API function that killer threads can call that will
terminate the
killee thread only after all the killee's cleanup handlers are executed?

If either of the answers to these two questions is "No", then I would think that
there is no
"safe" way of "externally killing a thread" in Win32.

-- Steve Flynn


John D. Hickin

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

yeb...@usa.net wrote:
>
> Hi,

>
> What is the safest way to kill a thread externally? There is a chance that if
> the tread processing takes to long I will have to terminate it from outside
> the thread. This can happen within a Winsock I/O function so I cannot just
> set a flag to terminate the thread from within the thread itself.
>
> I'd appreceate it if anybody has any ideas.
>
> Thanks!!!
>
> Yaakov Blank
> yeb...@usa.net
>
> -----== Posted via Deja News, The Leader in Internet Discussion ==-----
> http://www.dejanews.com/ Now offering spam-free web-based newsreading

This is just off the top of my head -- I havn't ever tried it before.
The general idea is like that of using CreateRemoteThread with thread
start function ExitProcess to kill a process: in this case you have to
queue an async procedure call which calls ExitThread. The thread has to
be in an alertable wait if this has any hope of success, so the coder
has to use WaitForSingleObjectEx.

Message has been deleted

Dave Butenhof

unread,
Jun 5, 1998, 3:00:00 AM6/5/98
to

Stephen Flynn wrote:

> yeb...@usa.net wrote:
>
> > What is the safest way to kill a thread externally? There is a chance that if
> > the tread processing takes to long I will have to terminate it from outside
> > the thread. This can happen within a Winsock I/O function so I cannot just
> > set a flag to terminate the thread from within the thread itself.
>

> What do you mean by safest? I prefer the binary model when it comes to thread
> termination: safe or unsafe. I am not as familiar with the Win32 threading model
> as the POSIX model. TerminateThread() is definitely unsafe.

This is absolutely correct. TerminateThread is never safe. You may leave arbitrary
data invariants busted, and arbitrary resources stranded. At absolute best, use of
TerminateThread represents a resource leak -- and even that requires a great deal of
luck. Never terminate a thread that has ANY sort of resources or persistent state.
You might as well just kill the process...

That advice is really the only part of Stephen's reply that's really relevent, since
the question was clearly about Windows, which lacks any sort of POSIX support.
Still, since Stephen went on to talk about POSIX cancellation, I'm going to go on
and make some comments and corrections.

> Allow me to give you a circuitous but, I hope, meaningful reply.
>
> In POSIX when a thread's cancelability type is set to PTHREAD_CANCEL_ASYNCHRONOUS,
> the thread can be canceled at any time, possibly in the middle of a critical code
> section which does not contain a failure back-out path. When having a asynchronous
> cancelability type, a thread should
> not acquire any resources and should call only async-cancel-safe functions. If
> this advice is not followed, the thread needs to install cancellation handlers
> cleanup handlers for every resource it acquires. If cleanup handlers are not
> installed, acquired resources are not released when the thread is canceled.

Cleanup handlers won't help with async cancellation unless you're EXTREMELY careful
(and at least a little clairvoyant). Remember that an asynchronous cancellation may
occur at any point, even in the middle of a machine instruction if the hardware
supports interruptible instructions (e.g., on a VAX).

Therefore, if ANY state is changed while async cancel is enabled, "recovery" means
that you need some way to determine whether the state was actually changed, or
whether the cancellation occurred first. For example, if you were to be foolish
enough to call malloc with async cancel enabled (note that this is ILLEGAL, and
should you attempt it, you'll be severely punished by reality), and a cancel
occurred, all your cleanup handler could tell was whether your pointer was NULL or
not. (Assuming, of course, that it had been statically initialized to NULL, or
dynamically initialized before enabling asynchronous cancellation.) But the cancel
may have occurred within malloc, after the memory was allocated, but before it
returned. Or even after the return, but before the return value register was copied
into your pointer variable! Therefore, even a carefully coded and well intentioned
cleanup handler may be unable to avoid serious resource leaks.

That's only one of the many reasons that I strongly recommend you NEVER try to use
asynchronous cancel. Yeah, it's a little better than Win32's TerminateThread,
because at least you have the opportunity to try. Still, beware that your best
efforts will serve only to slightly lessen the damage done to your program.

> In a related vein, POSIX provides cancellation points, which are the only places a
> killee thread may be canceled if its cancelablity type is PTHREAD_CANCEL_DEFERRED
> (the default value for all threads).
>
> According to Dave Butenhof:
> ----------------------------------------
> "POSIX doesn't have select(), and, therefore, did not specify that it was a
> cancellation point. The Single UNIX Specification, Version 2, however, (UNIX98),
> does specify that select() is a cancellation point. [PROPERTY A:] Most POSIX
> thread implementations will already implement select() as a cancellation point,
> and any that are UNIX98 branded will be required to do so."
> ----------------------------------------
>

> According to POSIX, a thread needs to process a pending cancellation point request
> only if it is about to block indefinitely. This is the minimum requirement in
> processing cancellation requests. PROPERTY B: Most systems cancel the target
> thread if the thread is blocked indefintely inside a function that is a
> cancellation point,

This assertion is incorrect -- in fact, you've got it backwards. POSIX requires that
when a cancel is delivered to a thread blocked in a cancellable wait (e.g., read,
write, pthread_cond_wait), that wait must be interrupted. POSIX does not specify
whether cancellation will occur if a "cancellation point" does not actually block,
with the exception of pthread_testcancel. (Although the standard in several places
implies that cancellation should occur on nonblocking cancellation points, and it is
probably reasonable to expect that on most implementations it will occur.)

> So, combining PROPERTY B with Butenhof's PROPERTY A, we see that if a killee
> thread is in a socket i/o system call like select(), msgrcv(), etc., it can be
> cancelled. (In fact, in many implementations, if a function can return with an
> EINTR error, chances are that it is a cancellation point)

Yes, for non-POSIX routines, the general convention has been that any kernel call
that can return with EINTR should be a cancellation point. That is also the
philosophy that we adopted for the UNIX98 standard in determining additional
cancellation points.

POSIX (and UNIX98) has two lists of cancellation points. One is a list of functions
(mostly kernel calls) that MUST BE cancellation points, and a second list of
functions that MAY BE cancellation points. The actual distinction was that the
functions in the second list are library (usually libc) functions that use kernel
calls from the first list. These functions are not required to test for
cancellation, but may be cancellation points should they actually call a
cancellation point. (For example, printf might deliver a cancel only when it
actually calls write to flush a stdio buffer.) Additionally, these functions may
disable cancellation around the kernel calls to avoid dealing with cleanup handlers,
or may allow the cancellation and handle it, depending on which strategy is more
convenient for the implementors.

> I don't recall Win32 providing the functionality of PTHREAD_CANCEL_DEFERRED. So
> that leaves the functionality of PTHREAD_CANCEL_ASYNCHRONOUS.
>
> So my question is: In Win32, (1) can a killee thread install cleanup handlers for
> every resource it acquires, and (2) is there a API function that killer threads
> can call that will terminate the killee thread only after all the killee's cleanup
> handlers are executed?

No, there are no cleanup handlers. Threads murdered with TerminateThread don't even
run DLL detach handlers.

> If either of the answers to these two questions is "No", then I would think that
> there is no "safe" way of "externally killing a thread" in Win32.

Absolutely correct. The best way is to implement your own deferred cancellation,
using some global state for each thread, that the thread polls "occasionally" at
convenient & appropriate times.

/---------------------------[ Dave Butenhof ]--------------------------\
| Digital Equipment Corporation bute...@zko.dec.com |
| 110 Spit Brook Rd ZKO2-3/Q18 http://members.aol.com/drbutenhof |
| Nashua NH 03062-2698 http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----------------[ Better Living Through Concurrency ]----------------/


Ian Johnston

unread,
Jun 11, 1998, 3:00:00 AM6/11/98
to

I once experimented with:

- suspending a thread
- getting its register set
- chaing the instruction pointer to point to a routine of my own devising
- setting the register set
- resuming the thread.

Omn resumption the thread would call my routine, which raised a Win32 structured
exception. My threads' "main" routines
had a __try/__except block which wrapped the real work routines.

This worked nicely, but with sporadic problems. Sometimes it worked great, sometimes
everything would hang.

I eventually realised that the Micsosoft C RTL uses an internal mutex to serialise
various calls (e.g. printf()). If this mutex
is held by the thread when you "kill" it, the mutex is not released; the next thread
that tries to call one of these serialised
RTL routines then simply hangs waiting for the mutex. Eventually, every thread would
hang on this mutex.

The only alternative I can see is to avoid the use of such serialised routines; and
without a detailed list of which routines
those are, in practice the only safe course seems to be avoid the C RTL.

In addition, my Win32 exception handlers did not clean up any other resources the
threads may have been holding. I
have come to the conslusion that the only safe way to do this is th have each thread
periodically check whether it
has been "requested to cancel" at a time when it can safely and cleanly release
resources.


John D. Hickin wrote:

> yeb...@usa.net wrote:
> >
> > Hi,


> >
> > What is the safest way to kill a thread externally? There is a chance that if
> > the tread processing takes to long I will have to terminate it from outside
> > the thread. This can happen within a Winsock I/O function so I cannot just
> > set a flag to terminate the thread from within the thread itself.
> >

> > I'd appreceate it if anybody has any ideas.
> >
> > Thanks!!!
> >
> > Yaakov Blank
> > yeb...@usa.net
> >
> > -----== Posted via Deja News, The Leader in Internet Discussion ==-----
> > http://www.dejanews.com/ Now offering spam-free web-based newsreading
>
> This is just off the top of my head -- I havn't ever tried it before.
> The general idea is like that of using CreateRemoteThread with thread
> start function ExitProcess to kill a process: in this case you have to
> queue an async procedure call which calls ExitThread. The thread has to
> be in an alertable wait if this has any hope of success, so the coder
> has to use WaitForSingleObjectEx.

--
Ian Johnston, FX Architecture, UBS, Zurich

0 new messages