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

Windows' ExitThread() and clasess' destructors

263 views
Skip to first unread message

Camilo Bravo Valdés

unread,
Oct 15, 2011, 8:18:00 AM10/15/11
to
Hello.

I have read that some Windows API functions like ExitThread() do not
call the destructors of classes. Is this true? Is then useless to
follow the RAII principle when working with the Windows API? Are there
"safer" versions of this function?
{ OS independant replies only please - mod}

Thanks in advance,
Camilo


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

red floyd

unread,
Oct 15, 2011, 11:59:29 AM10/15/11
to
On 10/15/2011 5:18 AM, Camilo Bravo Valdés wrote:
> Hello.
>
> I have read that some Windows API functions like ExitThread() do not
> call the destructors of classes. Is this true? Is then useless to
> follow the RAII principle when working with the Windows API? Are there
> "safer" versions of this function?
> { OS independant replies only please - mod}
>

I think this is common to all threading API's. C++11 may fix this,
but if you're using an C++03 compiler, try defining a special exception,
and catch it only in the top level thread function. The exception
propagation will call your destructors and then when you exit the top
level thread function, the thread will terminate.


struct TerminateThread {
int const exit_code;
TerminateThread(int x) : exit_code(x) { }
};

int thread_function()
{
try {
// do stuff
// exit normally
}
catch (TerminateThread e) {
return e.exit_code;

David Lowndes

unread,
Oct 15, 2011, 11:59:30 AM10/15/11
to
> I have read that some Windows API functions like ExitThread() do not
> call the destructors of classes. Is this true?

That's what the documentation says.

> Is then useless to
> follow the RAII principle when working with the Windows API?

Not at all. ExitThread and similar thread/process functions are really
intended as a last resort, they are not the normal way of exiting a
thread.

Dave

Goran

unread,
Oct 17, 2011, 5:48:50 PM10/17/11
to
On Oct 15, 2:18 pm, Camilo Bravo Valdés <kmilo.br...@gmail.com> wrote:
> Hello.
>
> I have read that some Windows API functions like ExitThread() do not
> call the destructors of classes. Is this true? Is then useless to
> follow the RAII principle when working with the Windows API? Are there
> "safer" versions of this function?
> { OS independant replies only please - mod}

There are functions that do not return, like the one you mention. So,
to enforce things like RAII, you simply must not use them. Note that
RAII is but one example, as any locally-scoped resource might be in
danger with such calls.

That said... You might be trying to terminate a thread forcibly, from
another thread. That's poor, poor programming practice, exactly for
reason mentioned above: you lose control of any locally-scoped
resources and possibly other things with thread affinity. Correct way
to "terminate" a thread is to ask it to terminate and then wait for
it. Thread code itself, must be aware that it can be asked to stop at
any given moment, and it has to be written to be able to do so. Best
practical way to do this is to:

* create a particular exception type (e.g. your own class). Possibly
hide it from thread code so that it can't possibly catch it, because
it shouldn't ever do that.
* expose something like check_termination function to thread code
* call said function from various places in thread code so that thread
can terminate in a timely fashion.

The above is about the only correct manner, ever, to "terminate" a
thread in general. Anything else can be done just under massive
constraints on what thread code does.

Goran.

Chris Vine

unread,
Oct 18, 2011, 3:46:36 PM10/18/11
to
On Mon, 17 Oct 2011 14:48:50 -0700 (PDT)
Goran <goran...@gmail.com> wrote:
> There are functions that do not return, like the one you mention. So,
> to enforce things like RAII, you simply must not use them. Note that
> RAII is but one example, as any locally-scoped resource might be in
> danger with such calls.
>
> That said... You might be trying to terminate a thread forcibly, from
> another thread. That's poor, poor programming practice, exactly for
> reason mentioned above: you lose control of any locally-scoped
> resources and possibly other things with thread affinity. Correct way
> to "terminate" a thread is to ask it to terminate and then wait for
> it.

As it happens C++11 came close to including provision for thread
interruption; but because either cancellation or your "suicide
request" approach requires blocking system calls to be interrupted in
some way in order to be fully effective, any complete system is
intrinsically non-portable.

More generally, I think you are making too broad a statement, as either
approach (cancellation or suicide request) depends on the implementation
and in particular the platform. All modern commercial unixes and most
recent BSDs/linuxes will unwind the stack on deferred cancellation by
means of a pseudo-exception when run under a C++ environment, and this
is a good language fit. With appropriate setting of thread
cancellation status (so the thread receiving the cancellation request
can nominate its own cancellation points) it is indistinguishable in
effect from finding a way to request the receiving thread to terminate
itself and throw its own exception.

However, as I said, this is OS dependent. Getting a blocking system call
to unblock on cancellation or "finding a way to request the receiving
thread to terminate itself" when in a blocking call (say by a signal),
which is essential to many real-life use cases, is considerably easier
under unix-like OSes. Indeed windows never used to offer deferred
cancellation at all (I don't know if it does now).


Chris

Goran

unread,
Oct 19, 2011, 9:00:23 AM10/19/11
to
On Oct 18, 9:46 pm, Chris Vine <ch...@cvine--nospam--.freeserve.co.uk>
wrote:
> On Mon, 17 Oct 2011 14:48:50 -0700 (PDT)
>
> Goran <goran.pu...@gmail.com> wrote:
> > There are functions that do not return, like the one you mention. So,
> > to enforce things like RAII, you simply must not use them. Note that
> > RAII is but one example, as any locally-scoped resource might be in
> > danger with such calls.
>
> > That said... You might be trying to terminate a thread forcibly, from
> > another thread. That's poor, poor programming practice, exactly for
> > reason mentioned above: you lose control of any locally-scoped
> > resources and possibly other things with thread affinity. Correct way
> > to "terminate" a thread is to ask it to terminate and then wait for
> > it.
>
> As it happens C++11 came close to including provision for thread
> interruption; but because either cancellation or your "suicide
> request" approach requires blocking system calls to be interrupted in
> some way in order to be fully effective, any complete system is
> intrinsically non-portable.

I agree. I am pretty certain that in a "real-world" codebase there's
going to be many blocking calls with no means of interrupting them,
system or otherwise, and that someone has to write some code for those
to either not take too long, either to become interruptible. BTW, what
do you mean by "C++11 came close to..."? I took a brief look at
std::thread, I see nothing on the line of interruption...

> More generally, I think you are making too broad a statement, as either
> approach (cancellation or suicide request) depends on the implementation
> and in particular the platform. All modern commercial unixes and most
> recent BSDs/linuxes will unwind the stack on deferred cancellation by
> means of a pseudo-exception when run under a C++ environment, and this
> is a good language fit. With appropriate setting of thread
> cancellation status (so the thread receiving the cancellation request
> can nominate its own cancellation points) it is indistinguishable in
> effect from finding a way to request the receiving thread to terminate
> itself and throw its own exception.
>
> However, as I said, this is OS dependent. Getting a blocking system call
> to unblock on cancellation or "finding a way to request the receiving
> thread to terminate itself" when in a blocking call (say by a signal),
> which is essential to many real-life use cases, is considerably easier
> under unix-like OSes. Indeed windows never used to offer deferred
> cancellation at all (I don't know if it does now).

On windows, I've been using so-called overlapped I/O, with waiting on
both I/O and a "cancellation" event with some success ;-).

Goran.

Chris Vine

unread,
Oct 20, 2011, 4:24:16 AM10/20/11
to
On Wed, 19 Oct 2011 06:00:23 -0700 (PDT)
Goran <goran...@gmail.com> wrote:
> On Oct 18, 9:46 pm, Chris Vine <ch...@cvine--nospam--.freeserve.co.uk>
> wrote:
[snip]
> > As it happens C++11 came close to including provision for thread
> > interruption; but because either cancellation or your "suicide
> > request" approach requires blocking system calls to be interrupted
> > in some way in order to be fully effective, any complete system is
> > intrinsically non-portable.
>
> I agree. I am pretty certain that in a "real-world" codebase there's
> going to be many blocking calls with no means of interrupting them,
> system or otherwise, and that someone has to write some code for those
> to either not take too long, either to become interruptible. BTW, what
> do you mean by "C++11 came close to..."? I took a brief look at
> std::thread, I see nothing on the line of interruption...

There is probably a language issue here, but I said "came close to
including" not "does include". You can look at the WG21 working papers
if you want to read more about it. If you want to examine what form it
might have taken, see boost's thread interruption and some of the early
WG21 papers based on it.

On blocking system calls as cancellation points, this is already
completely specified on POSIX platforms and doesn't need anyone to
write anything: in effect all blocking system calls are made
cancellation points unless the receiving thread has set itself to
refuse deferred cancellation requests at that point. (If the moderator
permits it, this is in System Interfaces, section 2.9.2, Cancellation
Points, of the SUS: if not, moderator please remove these words in
perenthesis, but I think the reference is of use in this discussion by
demonstrating the inherent non-portability of thread cancellation).

If you want to write cancellable code you must write it with
cancellation in mind, just as if you want to write thread safe code you
must write it with thread safety in mind. Or if you want to write
exception safe code, you must write it with exceptions in mind. If
that was your main point, then I agree.

Chris
0 new messages