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




> Alexander, it is not clear to me what you are strongly disagreeing
> with... my recommendation? (and it is not solely my recommendation,
> I can quote oodles of books recommending the same approach)

Yes.

> However, pthread_cancel is not documented as working in
> tandem with C++ stack unwinding.

I believe that it should be documented that a version
of pthreads-win32 library meant to be used in C++ programs
DOES work in tandem with C++ stack unwinding. Note that it
has nothing to do with a version of pthreads-win32 library
meant to be used in pure C programs.

> I would not recommend using it in a C++ application.

Personally, I disagree strongly with this approach.
I would ask pthread-lib vendor to provide C++ aware
pthread library, instead.

> To deal with "cancel",
> I would recommend representing a unit of work (i.e. a task)
> as an object that supports it's own ability to "cancel".
> A thread is just a means to an end... you want to do
> a unit of work. A unit of work could be executed directly,
> or within a thread, or tasked through a thread pool. The
> easiest, consistent, method of cancelling it is to cancel
> the task, not the "worker" trying to do the task.

Jobs/Tasks are OK, but they are not threads.
pthread_cancel and _exit are designed for threads.

> The only advantage that pthread_cancel has (on unix, that is)
> is that some basic C library methods that block are cancellable
> by pthread_cancel. You don't have this luxury on win32 unless you
> re-write the C runtime library with pthreads-win32.

Well, for example, how about waiting on condition
variable? That is a cancellation point that works
even with pthreads-win32. I do not want to replace
it with modified predicates which would include
"me->canceled()" flag. I do not want to know which
mutexes need to be locked and which condition variables
need to be signaled/broadcasted for a particular thread
to archive the effect meant to be provided by the
pthread_cancel.

I just want that in addition to C thread cleanup
handlers, thread cancel/exit would invoke C++
destructors and "catch(...)" handlers.

regards,
alexander.


"Bossom, John" <John.Bossom@Cognos.COM>@sources.redhat.com on 12/19/2001
03:00:58 PM

Sent by:  pthreads-win32-owner@sources.redhat.com


To:   Alexander Terekhov/Germany/IBM@IBMDE,
      pthreads-win32@sources.redhat.com
cc:
Subject:  RE: pthreads VCE: problem with destructor



Alexander, it is not clear to me what you are strongly disagreeing
with... my recommendation? (and it is not solely my recommendation,
I can quote oodles of books recommending the same approach)

However, pthread_cancel is not documented as working in
tandem with C++ stack unwinding. I would not recommend
using it in a C++ application.

To deal with "cancel",
I would recommend representing a unit of work (i.e. a task)
as an object that supports it's own ability to "cancel".
A thread is just a means to an end... you want to do
a unit of work. A unit of work could be executed directly,
or within a thread, or tasked through a thread pool. The
easiest, consistent, method of cancelling it is to cancel
the task, not the "worker" trying to do the task.
The only advantage that pthread_cancel has (on unix, that is)
is that some basic C library methods that block are cancellable
by pthread_cancel. You don't have this luxury on win32 unless you
re-write the C runtime library with pthreads-win32.

Just my 2 cents.

Good Luck,

John.


-----Original Message-----
From: Alexander Terekhov [mailto:TEREKHOV@de.ibm.com]
Sent: December 19, 2001 7:41 AM
To: pthreads-win32@sources.redhat.com
Subject: Re: pthreads VCE: problem with destructor



> > 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.

How about pthread_cancel? Are you saying that I should
never use it in a threaded C++ program for the same
reason(s) as pthread_exit?

Personally, I disagree strongly with this approach.

FYI:

http://groups.google.com/groups?as_umsgid=362DCB0D.230D900%40zko.dec.com
http://groups.google.com/groups?as_umsgid=kZ7h7.623%24bB1.30401%40news.cpqco

rp.net
http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51A_HTML/ARH9RB

TE/DOCU0004.HTM#cancel_excep_sec
http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51A_HTML/ARH9RB

TE/DOCU0001.HTM#index_x_53

"Several Threads Library features and most Threads Library
 identifiers are provided as C language macros. As such,
 their definitions may not be available in other languages.
 Developers working in other languages will have to provide
 their own declarations of functions and constants, and
 features such as TRY/CATCH exception handling and POSIX
 push/pop cleanup handlers may be completely unavailable
 (although it may be possible to provide similar
 functionality using native exception handling facilities).
 Note that in this context, C++ is a non-C language;
 while the C language macros may compile successfully
 under C++, TRY/CATCH and push/pop cleanup handlers
 are not supported for C++ code. C++ code should use
 object descructors and C++ exception handlers. "
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51A_HTML/ARH9RB

TE/DOCU0011.HTM#excep_defs

"Exception         Definition
 ================  ===================================
 pthread_cancel_e  Thread cancelation in progress
 .
 .
 .
 pthread_exit_e    Thread exiting using pthread_exit()"

regards,
alexander.


Ross Johnson <rpj@ise.canberra.edu.au>@sources.redhat.com on 12/19/2001
12:37:59 PM

Please respond to rpj@ise.canberra.edu.au

Sent by:  pthreads-win32-owner@sources.redhat.com


To:   "Bossom, John" <John.Bossom@Cognos.COM>
cc:   "'Gardian, Milan'" <Milan.Gardian@LEIBINGER.com>,
      "Pthreads-Win32@Sources.Redhat.Com"
      <pthreads-win32@sources.redhat.com>
Subject:  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.



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]