From: "Bossom, John" <John.Bossom@Cognos.COM>
To: "'Gardian, Milan'" <Milan.Gardian@LEIBINGER.com>,
"Pthreads-Win32@Sources.Redhat.Com"
<pthreads-win32@sources.redhat.com>
Cc: "Ross Johnson (E-mail)" <rpj@ise.canberra.edu.au>
Subject: RE: pthreads VCE: problem with destructor
Date: Tue, 18 Dec 2001 12:22:00 -0000 [thread overview]
Message-ID: <430F887D415DD1118C2700805F31ECF106B58985@sota0005.cognos.com> (raw)
Message-ID: <20011218122200.Fke2Fx34P3XN-oE_IRmSHzaGEmmbsFXtJc-1YHflDsk@z> (raw)
<Yes - I'm not going to lurk over this one... Hi Ross - I'm still here)
You are entering dark territory here. You are assuming that
Operating System primitives actually cooperate with C++ primitives (i.e
exception handling, implicit
call of local destructors)
This is not the case. At the time of implementation of pthread_win32
(original version) pthread_exit on UNIX did NOT call the C++ destructors
and perform graceful stack unwinding. pthread_exit basically did an end run
exit and locally called all registered pthread cleanup methods.
Recommended approach when using C++ in conjunction with pthreads is to
NEVER use pthread_exit... you should have your code return to your
thread mainline (use exceptions if you choose) and simply "return"
from the thread mainline.
If you (Ross) implement this marrying of C++ stack-unwinding with
pthread_exit, I suggest you
document that it is not typical behavior and you can expect that if you port
your code back
to various unix platforms that actually support pthreads natively, you
will encounter exactly the same problem.
-----Original Message-----
From: Gardian, Milan [ mailto:Milan.Gardian@LEIBINGER.com ]
Sent: December 18, 2001 9:17 AM
To: Pthreads-Win32@Sources.Redhat.Com
Cc: Ross Johnson (E-mail)
Subject: pthreads VCE: problem with destructor
Hi,
I came across a problem with pthreads VCE: destructors for objects in local
scope (automatic variables on stack) of the thread-function are not called
when using 'pthread_exit' to exit the thread (or when using any function
that eventually throws a C++ exception (because of VCE build) using
ptw32_throw internal function).
To illustrate this point I created a new test case, 'exit4.c'. It uses a C++
guard object to increment a shared reference count in constructor and
decrement it in destructor. This object is then created on stack in both the
main thread (before creating the new thread) and in the thread-function
(i.e. reference count is increased by 2).
If we finish the thread-function by returning from it (falling off the end),
destructor for both objects is called as expected (first the thread-function
local object and then the main thread local object). This case is
illustrated by commenting out the macro USE_PTHREAD_EXIT in exit4.c, line 11
-> the test case passes.
On the other hand if we finish the thread-function by using 'pthread_exit'
instead of falling off the end, the destructor for the thread-function local
object is NOT called (although the destructor for main thread local object
is called). This case is illustrated by compiling with the macro
USE_PTHREAD_EXIT in exit4.c, line 11 -> the test case fails.
C++ resource idiom (acquire in constructor, release in destructor) is used
throughout our threaded program. The described behaviour of pthreads is
introducing possibility of a resource leak and potential deadlock. Does
anybody have any ideas what is happening and how to resolve the problem?
Thank you very much for your replies and help,
Cheers,
Milan
PS0: My config -> SMP 2 x PIII/500, W2k SP1, VC++ 6 SP4, Platform SDK
June/2001, pthreads-latest-2001_12_17 (snaphost of the CVS taken on
17-DEC-2001 by Ross)
PS1: Note that the reference counting need not be protected by a mutex as it
will never be accessed simultaneously by both threads due to synchronization
using pthread_join.
PS2: The exit4.c file
===================================
/*
* Test for pthread_exit().
*
* Depends on API functions: pthread_create().
*/
#include "test.h"
#ifdef __cplusplus
#define USE_PTHREAD_EXIT
static const int init_counter_value = 3;
static void *ret_value = reinterpret_cast<void *>(1);
static int counter = init_counter_value;
class Guard
{
const char * const _str;
int &_ref;
Guard &operator=(const Guard&);
Guard(const Guard&);
public:
Guard(const char * const str, int &ref) : _str(str), _ref(ref) {
printf("Construct %s [%d->%d]\n", _str, _ref, _ref+++1);
};
~Guard() {
printf("~Destruct %s [%d->%d]\n", _str, _ref, _ref---1);
};
};
void *
func(void * arg)
{
Guard g("func", counter);
#ifdef USE_PTHREAD_EXIT
pthread_exit(arg);
assert(0); //Never reached with pthread_exit
#endif //USE_PTHREAD_EXIT
return ret_value;
}
#endif /*__cplusplus */
int main(int, char **)
{
#ifndef __cplusplus
printf("Test requires C++. Skipped.\n");
#else
{
void *ret = 0;
Guard g("main", counter);
pthread_t id;
assert(0 == pthread_create(&id, 0, func, ret_value));
assert(0 == pthread_join(id, &ret));
assert(ret == ret_value);
}
assert(counter == init_counter_value);
#endif /*__cplusplus */
return 0;
}
===================================
PS3: Changes to the 'tests/Makefile' (diff file, use patch):
===================================
--- ..\..\pthreads\tests\Makefile Fri Oct 26 12:12:48 2001
+++ Makefile Tue Dec 18 14:16:00 2001
@@ -41,7 +41,7 @@
mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass mutex2.pass
mutex3.pass \
condvar1.pass condvar2.pass condvar2_1.pass \
exit1.pass create1.pass equal1.pass \
- exit2.pass exit3.pass \
+ exit2.pass exit3.pass exit4.pass \
join0.pass join1.pass join2.pass \
mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass
\
count1.pass once1.pass tsd1.pass \
@@ -186,6 +186,7 @@
exit1.pass:
exit2.pass: create1.pass
exit3.pass: create1.pass
+exit4.pass: create1.pass
eyal1.pass: tsd1.pass
inherit1.pass: join1.pass
join0.pass: create1.pass
===================================
This message may contain privileged and/or confidential information. If you
have received this e-mail in error or are not the intended recipient, you
may not use, copy, disseminate, or distribute it; do not open any
attachments, delete it immediately from your system and notify the sender by
e-mail promptly that you have done so. Thank You.
next reply other threads:[~2001-12-18 12:22 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-01-11 7:04 Bossom, John [this message]
2001-01-15 7:40 ` Ross Johnson
2001-01-24 14:02 ` reentrant
2001-03-10 6:41 ` Thomas Pfaff
2001-12-20 1:25 ` Thomas Pfaff
2001-12-19 10:22 ` reentrant
2001-12-19 3:38 ` Ross Johnson
2001-12-18 12:22 ` Bossom, John
-- strict thread matches above, loose matches on Subject: below --
2001-03-22 11:41 Bossom, John
2001-12-20 8:46 ` Bossom, John
2001-03-22 11:39 Alexander Terekhov
2001-12-20 6:08 ` Alexander Terekhov
2001-03-22 11:19 Thomas Pfaff
2001-12-20 4:40 ` Thomas Pfaff
2001-03-12 5:53 Alexander Terekhov
2001-12-20 2:35 ` Alexander Terekhov
2001-02-23 8:35 Bossom, John
2001-12-19 13:19 ` Bossom, John
2001-02-01 6:46 Alexander Terekhov
2001-12-19 11:30 ` Alexander Terekhov
2001-01-24 21:42 Alexander Terekhov
2001-12-19 11:01 ` Alexander Terekhov
2001-01-16 16:48 Bossom, John
2001-12-19 6:02 ` Bossom, John
2001-01-16 7:38 Alexander Terekhov
2001-12-19 4:40 ` Alexander Terekhov
2001-01-16 1:18 Gardian, Milan
2001-12-19 4:05 ` Gardian, Milan
2001-01-11 6:04 Mike Kinghan
2001-12-18 7:00 ` Mike Kinghan
2001-01-05 8:30 Gardian, Milan
2001-12-18 6:18 ` Gardian, Milan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=430F887D415DD1118C2700805F31ECF106B58985@sota0005.cognos.com \
--to=john.bossom@cognos.com \
--cc=Milan.Gardian@LEIBINGER.com \
--cc=pthreads-win32@sources.redhat.com \
--cc=rpj@ise.canberra.edu.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).