This is the mail archive of the pthreads-win32@sources.redhat.com mailing list for the pthreas-win32 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: pthreads VCE: problem with destructor


I sense a rising and ruthless desire to deal with the problem of
the exception-based versions of the library. It would certainly
be a lot easier if they weren't there, and there are some
hacks in pthread.h supporting them that really are nasty.

So ... what to do about them?

I will firstly put John's warning in the README file
and the README.NONPORTABLE file, and on the Web page.

Secondly, there is a standard C version of the library courtesy
of Thomas Pfaff's contributions. It uses setjmp/longjmp.
Does this need to be built differently to work with C++
applications (assuming they are written as John suggests they
should be)? I can try putting it through the VCE run of the
test suite as soon as I reinstall my corrupted Windows 98 machine.

Thirdly, if possible, consider phasing out all but the VC and GC
versions of the library (currently the only standard C versions).
That is, phase out the VCE, VSE, and GCE versions.

Does anyone wan't to jump up and shout - NO!!

Ross

"Bossom, John" wrote:
> 
> <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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]