Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #79723 > unrolled thread

Re: std::thread does not follow RAII principles

Started byMrSpook_ry@939_6htz773e0qeya.eu
First post2021-05-27 08:18 +0000
Last post2021-05-28 11:11 +0000
Articles 20 on this page of 54 — 11 participants

Back to article view | Back to comp.lang.c++

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: std::thread does not follow RAII principles MrSpook_ry@939_6htz773e0qeya.eu - 2021-05-27 08:18 +0000
    Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 11:02 +0200
      Re: std::thread does not follow RAII principles MrSpook_b28s@jxgz6zklebr1.tv - 2021-05-27 10:24 +0000
        Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 12:33 +0200
          Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 12:40 +0200
            Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 12:55 +0200
          Re: std::thread does not follow RAII principles MrSpook_d4c3Jb7l7@8dftupdzk09cop2.co.uk - 2021-05-27 11:05 +0000
            Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 13:14 +0200
              Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 13:18 +0200
              Re: std::thread does not follow RAII principles MrSpook_b_x@ukpge.org - 2021-05-27 15:54 +0000
                Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-27 19:32 +0200
                  Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-27 19:00 +0100
                    Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-27 17:52 -0700
                      Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 05:24 +0200
                        Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 05:27 +0200
                      Re: std::thread does not follow RAII principles Ian Collins <ian-news@hotmail.com> - 2021-05-28 14:59 +1200
                        Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-27 20:37 -0700
                          Re: std::thread does not follow RAII principles Ian Collins <ian-news@hotmail.com> - 2021-05-28 16:50 +1200
                            Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 06:53 +0200
                            Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-27 23:07 -0700
                              Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 08:26 +0200
                              Re: std::thread does not follow RAII principles Ian Collins <ian-news@hotmail.com> - 2021-05-28 21:01 +1200
                                Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 13:04 +0200
                                  Re: std::thread does not follow RAII principles Branimir Maksimovic <branimir.maksimovic@gmail.com> - 2021-05-28 17:06 +0000
                                    Re: std::thread does not follow RAII principles scott@slp53.sl.home (Scott Lurndal) - 2021-05-28 17:51 +0000
                                      Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 20:00 +0200
                                      Re: std::thread does not follow RAII principles Branimir Maksimovic <branimir.maksimovic@gmail.com> - 2021-05-28 21:42 +0000
                              Re: std::thread does not follow RAII principles Branimir Maksimovic <branimir.maksimovic@gmail.com> - 2021-05-28 17:03 +0000
                    Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 03:55 +0200
                      Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 12:02 +0100
                        Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 13:15 +0200
                          Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 12:40 +0100
                            Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 13:55 +0200
                              Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 13:57 +0200
                                Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 14:29 +0100
                                  Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 15:48 +0200
                                    Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 16:16 +0200
                                      Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 15:45 +0100
                                        Re: std::thread does not follow RAII principles Bonita Montero <Bonita.Montero@gmail.com> - 2021-05-28 17:30 +0200
                                          Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 19:54 +0100
                                    Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-28 15:08 +0100
                          Re: std::thread does not follow RAII principles Branimir Maksimovic <branimir.maksimovic@gmail.com> - 2021-05-28 17:08 +0000
                        Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-29 01:42 -0700
                          Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-29 13:05 +0100
                            Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-29 13:44 +0100
                              Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-29 06:34 -0700
                                Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-29 14:48 +0100
                                  Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-29 07:59 -0700
                                    Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-29 18:15 +0100
                                      Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-29 19:03 -0700
                                        Re: std::thread does not follow RAII principles Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2021-05-30 11:48 +0100
                                          Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-30 09:35 -0700
                            Re: std::thread does not follow RAII principles Öö Tiib <ootiib@hot.ee> - 2021-05-29 06:51 -0700
                  Re: std::thread does not follow RAII principles MrSpook_jx@zp238i0_j1.net - 2021-05-28 11:11 +0000

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#79848

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 08:26 +0200
Message-ID<s8q2fc$8nm$1@dont-email.me>
In reply to#79847
> When I do by hand, set some atomic flag (that thread checks if it
> should stop) and then join then I can measure, can mock that flag
> checking function. It is lot easier?

And if you load that flag relaxed and it is shared in several
cachelines of different cores the check is usually predicted
as false by the branch-prediction so that checking that flag
almost takes no overhead.

[toc] | [prev] | [next] | [standalone]


#79858

FromIan Collins <ian-news@hotmail.com>
Date2021-05-28 21:01 +1200
Message-ID<ihbpqmFt2e6U3@mid.individual.net>
In reply to#79847
On 28/05/2021 18:07, Öö Tiib wrote:
> On Friday, 28 May 2021 at 07:51:05 UTC+3, Ian Collins wrote:
>> On 28/05/2021 15:37, Öö Tiib wrote:
>>>
>>> Very interesting ... but magical solutions make me even more worried.
>>> Is there some kind of secret exception thrown or some kind of alternative
>>> stack unwinding used or what? If secret exception then does
>>> catch(...) { mopup(); throw; } work or has it to be full RAII? If alternative
>>> stack unwinding then what it costs and do noexcept(true) functions
>>> in call stack compile still into that rainbow table because of it?
>>
>> I believe (at lease on Solaris), the "magic" is the runtime using
>> pthread_cleanup_push/pthread_cleanup_pop to manage the destructor
>> calling, there's no need for exceptions. There's nothing to stop you
>> doing this by hand...
>>
>> There a a number of behaviours which fall between two standards and we
>> have to rely on the quality of the implementation, this just happens to
>> be one.
> 
> My threads typically do some sequential work that can be time consuming
> and complex (or otherwise why thread?). So I am unsure how to unit or
> automatic test canceling it cheaply enough as magic goes in the
> supernatural realm.
> 
> When I do by hand, set some atomic flag (that thread checks if it
> should stop) and then join then I can measure, can mock that flag
> checking function. It is lot easier?

That is certainly a very common paradigm, one  which my current day job 
application (being cross-platform) uses exclusively.  It is also one 
where C++ threads provide everything you need.

Cancellation is probably uncommon in current C++ applications (I had to 
go back to some of my old C++98 code to find a use case!) but it does 
have its usages and if needed, it is good to know that your C++ runtime 
handles object destruction correctly.

-- 
Ian.

[toc] | [prev] | [next] | [standalone]


#79865

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 13:04 +0200
Message-ID<s8qinp$h86$1@dont-email.me>
In reply to#79858
> Cancellation is probably uncommon in current C++ applications (I had to 
> go back to some of my old C++98 code to find a use case!) but it does 
> have its usages and if needed, it is good to know that your C++ runtime 
> handles object destruction correctly.

Have you ever checked how pthread_cleanup_push and pthead_cleanup_pop
works ? These are macros and generate something with do / while inter-
nally. What kind of bastard does design such ugly hacks ?

[toc] | [prev] | [next] | [standalone]


#79905

FromBranimir Maksimovic <branimir.maksimovic@gmail.com>
Date2021-05-28 17:06 +0000
Message-ID<Gq9sI.430718$J_5.215368@fx46.iad>
In reply to#79865
On 2021-05-28, Bonita Montero <Bonita.Montero@gmail.com> wrote:
>> Cancellation is probably uncommon in current C++ applications (I had to 
>> go back to some of my old C++98 code to find a use case!) but it does 
>> have its usages and if needed, it is good to know that your C++ runtime 
>> handles object destruction correctly.
>
> Have you ever checked how pthread_cleanup_push and pthead_cleanup_pop
> works ? These are macros and generate something with do / while inter-
> nally. What kind of bastard does design such ugly hacks ?
That is POSIX thing. Very old.


-- 
current job title: senior software engineer
skills: x86 aasembler,c++,c,rust,go,nim,haskell...

press any key to continue or any other to quit...

[toc] | [prev] | [next] | [standalone]


#79910

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-05-28 17:51 +0000
Message-ID<L4asI.5197$N%.3596@fx05.iad>
In reply to#79905
Branimir Maksimovic <branimir.maksimovic@gmail.com> writes:
>On 2021-05-28, Bonita Montero <Bonita.Montero@gmail.com> wrote:
>>> Cancellation is probably uncommon in current C++ applications (I had to 
>>> go back to some of my old C++98 code to find a use case!) but it does 
>>> have its usages and if needed, it is good to know that your C++ runtime 
>>> handles object destruction correctly.
>>
>> Have you ever checked how pthread_cleanup_push and pthead_cleanup_pop
>> works ? These are macros and generate something with do / while inter-
>> nally. What kind of bastard does design such ugly hacks ?
>That is POSIX thing. Very old.

Please don't feed the troll.

[toc] | [prev] | [next] | [standalone]


#79914

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 20:00 +0200
Message-ID<s8rb3l$dvg$1@dont-email.me>
In reply to#79910
>>>> Cancellation is probably uncommon in current C++ applications (I had to
>>>> go back to some of my old C++98 code to find a use case!) but it does
>>>> have its usages and if needed, it is good to know that your C++ runtime
>>>> handles object destruction correctly.

>>> Have you ever checked how pthread_cleanup_push and pthead_cleanup_pop
>>> works ? These are macros and generate something with do / while inter-
>>> nally. What kind of bastard does design such ugly hacks ?
>> That is POSIX thing. Very old.

> Please don't feed the troll.

Have I taken away one of your toys ?

[toc] | [prev] | [next] | [standalone]


#79928

FromBranimir Maksimovic <branimir.maksimovic@gmail.com>
Date2021-05-28 21:42 +0000
Message-ID<PsdsI.178763$lyv9.158958@fx35.iad>
In reply to#79910
On 2021-05-28, Scott Lurndal <scott@slp53.sl.home> wrote:
> Branimir Maksimovic <branimir.maksimovic@gmail.com> writes:
>>On 2021-05-28, Bonita Montero <Bonita.Montero@gmail.com> wrote:
>>>> Cancellation is probably uncommon in current C++ applications (I had to 
>>>> go back to some of my old C++98 code to find a use case!) but it does 
>>>> have its usages and if needed, it is good to know that your C++ runtime 
>>>> handles object destruction correctly.
>>>
>>> Have you ever checked how pthread_cleanup_push and pthead_cleanup_pop
>>> works ? These are macros and generate something with do / while inter-
>>> nally. What kind of bastard does design such ugly hacks ?
>>That is POSIX thing. Very old.
>
> Please don't feed the troll.

I beleive she pents significant time to show her code here, so she is not
really troll ;)


-- 
current job title: senior software engineer
skills: x86 aasembler,c++,c,rust,go,nim,haskell...

press any key to continue or any other to quit...

[toc] | [prev] | [next] | [standalone]


#79901

FromBranimir Maksimovic <branimir.maksimovic@gmail.com>
Date2021-05-28 17:03 +0000
Message-ID<ln9sI.430716$J_5.342512@fx46.iad>
In reply to#79847
On 2021-05-28, Öö Tiib <ootiib@hot.ee> wrote:
> On Friday, 28 May 2021 at 07:51:05 UTC+3, Ian Collins wrote:
>> On 28/05/2021 15:37, Öö Tiib wrote: 
>> > 
>> > Very interesting ... but magical solutions make me even more worried. 
>> > Is there some kind of secret exception thrown or some kind of alternative 
>> > stack unwinding used or what? If secret exception then does 
>> > catch(...) { mopup(); throw; } work or has it to be full RAII? If alternative 
>> > stack unwinding then what it costs and do noexcept(true) functions 
>> > in call stack compile still into that rainbow table because of it?
>> 
>> I believe (at lease on Solaris), the "magic" is the runtime using 
>> pthread_cleanup_push/pthread_cleanup_pop to manage the destructor 
>> calling, there's no need for exceptions. There's nothing to stop you 
>> doing this by hand... 
>> 
>> There a a number of behaviours which fall between two standards and we 
>> have to rely on the quality of the implementation, this just happens to 
>> be one. 
>
> My threads typically do some sequential work that can be time consuming
> and complex (or otherwise why thread?). So I am unsure how to unit or
> automatic test canceling it cheaply enough as magic goes in the
> supernatural realm.
>
> When I do by hand, set some atomic flag (that thread checks if it
> should stop) and then join then I can measure, can mock that flag
> checking function. It is lot easier? 
I think that using flags is more practical as it less error prone ;)
>


-- 
current job title: senior software engineer
skills: x86 aasembler,c++,c,rust,go,nim,haskell...

press any key to continue or any other to quit...

[toc] | [prev] | [next] | [standalone]


#79825

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 03:55 +0200
Message-ID<s8piij$1n3$1@dont-email.me>
In reply to#79787
> What you do is use deferred cancellation (the default in POSIX)
> and block cancellation as normal policy, and only enable cancellation
> at defined points in the code which are able to deal with it (normally
> where a wait is to occur).  Done properly, thread cancellation is far
> easier to use than exceptions, ...

Handling cancelation via flags and exceptions is cleaner and as easy
to handle. It's cleaner as it does honor destructors to be called inside
the stack. So never use Posix cancellation in C++-programs !

[toc] | [prev] | [next] | [standalone]


#79863

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2021-05-28 12:02 +0100
Message-ID<20210528120202.6e4865f5285cdca42766b5c8@cvine--nospam--.freeserve.co.uk>
In reply to#79825
On Fri, 28 May 2021 03:55:31 +0200
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> > What you do is use deferred cancellation (the default in POSIX)
> > and block cancellation as normal policy, and only enable cancellation
> > at defined points in the code which are able to deal with it (normally
> > where a wait is to occur).  Done properly, thread cancellation is far
> > easier to use than exceptions, ...
> 
> Handling cancelation via flags and exceptions is cleaner and as easy
> to handle. It's cleaner as it does honor destructors to be called inside
> the stack. So never use Posix cancellation in C++-programs !

All the common open source OS's (linux[1], the BSDs), and the commercial
Unixes (AIX, HPUX, Solaris) will unwind the stack on thread
cancellation in a C++ program.  With linux's NPTL as implemented by
glibc this occurs by the emission of a "pseudo-exception" which you can
catch with a catch-all but which (if you do catch it) you must rethrow
in your catch block - in other words, you cannot stop cancellation by
using a catch block once it has started but you can do clean-up.

The point about thread cancellation using deferred cancellation is that
nearly all the POSIX functions which can block in the kernel, including
blocking reads and condition variable waits, are specified as
cancellation points in the SUS, so any such blocking in the kernel will
be awoken by a cancellation request (assuming cancellation is not
blocked at that particular point in the code).  You cannot emulate that
in POSIX with flags and exeptions except by having a signal generate
EINTR so as to force the kernel wait in question to end in order to
check the flag, which has a number of undesirable effects of its own for
multi-threaded programs.  Furthermore some POSIX blocking functions
(including pthread_cond_wait) are specified as not interruptible by
EINTR.

On a unix-like OS, there is really no problem with thread cancellation
apart from a lack of familiarity arising from the fact it does not
feature in the C++ standard and is not usuably available on the windows
platform.

[1]  The former linuxthreads implementation from around 15 to 20 years
ago did not unwind the stack.  Any linux distributions over the last 10
years will use glibc's NPTL implementation, which does unwind the stack.

[toc] | [prev] | [next] | [standalone]


#79866

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 13:15 +0200
Message-ID<s8qjci$poj$1@dont-email.me>
In reply to#79863
> All the common open source OS's (linux[1], the BSDs), ...

Linux doesn't:

#include <iostream>
#include <limits>
#include <pthread.h>
#include <unistd.h>

using namespace std;

struct destr
{
     ~destr();
};

destr::~destr()
{
     cout << "destr::~destr()" << endl;
}

int main()
{
     auto thr = []( void * ) -> void *
     {
         cout << "thread is running" << endl;
         int oldStat;
         if(    pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldStat 
) != 0
             || pthread_setcanceltype( PTHREAD_CANCEL_ENABLE,   &oldStat 
) != 0 )
         {
             cout << "can't enable cancelling" << endl;
             return nullptr;
         }
         destr d;
         sleep( numeric_limits<int>::max() );
         return nullptr;
     };
     pthread_t pt;
     if( pthread_create( &pt, nullptr, thr, nullptr ) != 0 )
     {
         cout << "can't create thread" << endl;
         return -1;
     }
     if( pthread_cancel( pt ) != 0 )
     {
         cout << "can't cancel thread" << endl;
         return -1;
     }
     if( pthread_join( pt, nullptr ) != 0 )
     {
         cout << "can't join thread" << endl;
         return -1;
     }
}

And I hardly doubt that this works on most Unices.

[toc] | [prev] | [next] | [standalone]


#79870

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2021-05-28 12:40 +0100
Message-ID<20210528124032.7f6edf3a31673a5311121ec5@cvine--nospam--.freeserve.co.uk>
In reply to#79866
On Fri, 28 May 2021 13:15:28 +0200
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> > All the common open source OS's (linux[1], the BSDs), ...
> 
> Linux doesn't:
> 
> #include <iostream>
> #include <limits>
> #include <pthread.h>
> #include <unistd.h>
> 
> using namespace std;
> 
> struct destr
> {
>      ~destr();
> };
> 
> destr::~destr()
> {
>      cout << "destr::~destr()" << endl;
> }
> 
> int main()
> {
>      auto thr = []( void * ) -> void *
>      {
>          cout << "thread is running" << endl;
>          int oldStat;
>          if(    pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldStat 
> ) != 0
>              || pthread_setcanceltype( PTHREAD_CANCEL_ENABLE,   &oldStat 
> ) != 0 )
>          {
>              cout << "can't enable cancelling" << endl;
>              return nullptr;
>          }
>          destr d;
>          sleep( numeric_limits<int>::max() );
>          return nullptr;
>      };
>      pthread_t pt;
>      if( pthread_create( &pt, nullptr, thr, nullptr ) != 0 )
>      {
>          cout << "can't create thread" << endl;
>          return -1;
>      }
>      if( pthread_cancel( pt ) != 0 )
>      {
>          cout << "can't cancel thread" << endl;
>          return -1;
>      }
>      if( pthread_join( pt, nullptr ) != 0 )
>      {
>          cout << "can't join thread" << endl;
>          return -1;
>      }
> }
> 
> And I hardly doubt that this works on most Unices.

Comment out 'cout << "thread is running" << endl;' and try again.  I
doubt your doubt.

[toc] | [prev] | [next] | [standalone]


#79871

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 13:55 +0200
Message-ID<s8qlnu$bg5$1@dont-email.me>
In reply to#79870
> Comment out 'cout << "thread is running" << endl;' and try again.  I
> doubt your doubt.

	auto thr = []( void * ) -> void *
	{
		// cout << "thread is running" << endl;
		int oldStat;
		if(    pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldStat ) != 0
			|| pthread_setcanceltype( PTHREAD_CANCEL_ENABLE, &oldStat ) != 0 )
		{
			cout << "can't enable cancelling" << endl;
			return nullptr;
		}
		destr d;
		sleep( numeric_limits<int>::max() );
		cout << "after sleep" << endl;
		return nullptr;
	};

Ok, you're right - after sleep isn't called.
But is that relly guaranteed ?

[toc] | [prev] | [next] | [standalone]


#79872

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 13:57 +0200
Message-ID<s8qls0$bg5$2@dont-email.me>
In reply to#79871
Am 28.05.2021 um 13:55 schrieb Bonita Montero:
>> Comment out 'cout << "thread is running" << endl;' and try again.  I
>> doubt your doubt.
> 
>      auto thr = []( void * ) -> void *
>      {
>          // cout << "thread is running" << endl;
>          int oldStat;
>          if(    pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldStat 
> ) != 0
>              || pthread_setcanceltype( PTHREAD_CANCEL_ENABLE, &oldStat ) 
> != 0 )
>          {
>              cout << "can't enable cancelling" << endl;
>              return nullptr;
>          }
>          destr d;
>          sleep( numeric_limits<int>::max() );
>          cout << "after sleep" << endl;
>          return nullptr;
>      };
> 
> Ok, you're right - after sleep isn't called.
> But is that relly guaranteed ?
> 

But if you consider that commenting out the cout above makes the whole
thing working it doesn't look reliable.

[toc] | [prev] | [next] | [standalone]


#79875

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2021-05-28 14:29 +0100
Message-ID<20210528142900.3d1aa5be0fe09868849d180a@cvine--nospam--.freeserve.co.uk>
In reply to#79872
On Fri, 28 May 2021 13:57:51 +0200
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> Am 28.05.2021 um 13:55 schrieb Bonita Montero:
> >> Comment out 'cout << "thread is running" << endl;' and try again.  I
> >> doubt your doubt.
> > 
> >      auto thr = []( void * ) -> void *
> >      {
> >          // cout << "thread is running" << endl;
> >          int oldStat;
> >          if(    pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldStat 
> > ) != 0
> >              || pthread_setcanceltype( PTHREAD_CANCEL_ENABLE, &oldStat ) 
> > != 0 )
> >          {
> >              cout << "can't enable cancelling" << endl;
> >              return nullptr;
> >          }
> >          destr d;
> >          sleep( numeric_limits<int>::max() );
> >          cout << "after sleep" << endl;
> >          return nullptr;
> >      };
> > 
> > Ok, you're right - after sleep isn't called.
> > But is that relly guaranteed ?
> > 
> 
> But if you consider that commenting out the cout above makes the whole
> thing working it doesn't look reliable.

No, that's nothing to do with cancellation; it's to do with threads
and static objects. If you amend your first version to issue a print
statement in the constructor instead of the destructor, that won't print
either.  It appears that std::cout isn't properly available to the
worker thread when it is first launched (that is, before the sleep).

I would need to look it up but it looks as if there is an optimization
bug in g++ concerning the std::cout static object as I believe
std::cout is required to be ready when main is entered and so when the
thread is entered.  As it happens there is a get-out clause for the
optimizer because your code has undefined behaviour: your code can emit
"can't cancel thread" and "can't join thread" in the main thread without
synchronization. (As to the second of those, if pthread_join fails
there is no synchronization.)

If you test with a boolean flag rather than using std::cout in the
worker thread you will see that the cancellation is working in the
expected way.

[toc] | [prev] | [next] | [standalone]


#79877

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 15:48 +0200
Message-ID<s8qsar$2n4$1@dont-email.me>
In reply to#79875
> No, that's nothing to do with cancellation; it's to do with threads
> and static objects. If you amend your first version to issue a print
> statement in the constructor instead of the destructor, that won't print
> either.  It appears that std::cout isn't properly available to the
> worker thread when it is first launched (that is, before the sleep).

It's not about cout not being workig - it works always -,
it's about cancellation not to work if I activate the cout.

[toc] | [prev] | [next] | [standalone]


#79878

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 16:16 +0200
Message-ID<s8qtvo$dgu$1@dont-email.me>
In reply to#79877
> Immediately pthread_create() returns you call pthread_cancel().
> However you write to std::cout with "thread is running" without
> setting a cancel block. ...

The thread doesn't need to enable cancelling for a cancel-request
to be hold in the queue; a cancel-request is also enqueued if the
thread hasn't enabled cancelling yet.

> The write to std::cout will operate on POSIX primitives such as
> write which are cancellation points, so the worker thread is
> cancelled on its first write to cout, which is not your intention.

I think the thread isn't cancelled at this point since I've not
enabled cancelling then.

[toc] | [prev] | [next] | [standalone]


#79883

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2021-05-28 15:45 +0100
Message-ID<20210528154550.de83787a977549f18c552595@cvine--nospam--.freeserve.co.uk>
In reply to#79878
On Fri, 28 May 2021 16:16:21 +0200
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> > Immediately pthread_create() returns you call pthread_cancel().
> > However you write to std::cout with "thread is running" without
> > setting a cancel block. ...
> 
> The thread doesn't need to enable cancelling for a cancel-request
> to be hold in the queue; a cancel-request is also enqueued if the
> thread hasn't enabled cancelling yet.
> 
> > The write to std::cout will operate on POSIX primitives such as
> > write which are cancellation points, so the worker thread is
> > cancelled on its first write to cout, which is not your intention.
> 
> I think the thread isn't cancelled at this point since I've not
> enabled cancelling then.

You are making this quite hard work.  For new threads (including the
main thread), cancellation is enabled by default, and also deferred by
default.  Your code making cancellation deferred can be omitted.  You
must also set cancellation state with pthread_setcancelstate, not with
pthread_setcanceltype as in your code.

So omit your calls to  pthread_setcanceltype which are in the first
case otiose and in the second case both otiose and incorrect.

Then add this to your worker thread as the first thing it does:

  pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldState ) ;

And add this immediately before your call to sleep:

  pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldState ) ;

[toc] | [prev] | [next] | [standalone]


#79894

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-05-28 17:30 +0200
Message-ID<s8r2bf$enq$1@dont-email.me>
In reply to#79883
> You are making this quite hard work.  For new threads (including the
> main thread), cancellation is enabled by default, ...

Ok, that's what I didn't consider.

[toc] | [prev] | [next] | [standalone]


#79918

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2021-05-28 19:54 +0100
Message-ID<20210528195413.bca4ea7428c8c0357aa99704@cvine--nospam--.freeserve.co.uk>
In reply to#79894
On Fri, 28 May 2021 17:30:52 +0200
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> > You are making this quite hard work.  For new threads (including the
> > main thread), cancellation is enabled by default, ...
> 
> Ok, that's what I didn't consider.

And in case any readers think there is a race between the parent
thread's call to pthread_cancel and the worker thread's call to
pthread_setcancelstate as its first action, I should mention that there
isn't: this is because pthread_setcancelstate is not a cancellation
point.  POSIX's thread cancellation, as extended for C++, is pretty well
thought through in my opinion.

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c++


csiph-web