On Jul 17 16:21, Corinna Vinschen wrote:
> On Jul 17 12:51, Jon Turney wrote:
> > On 17/07/2023 12:05, Corinna Vinschen wrote:
> > > diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
> > > index f614e01c42f6..fceb9bda1806 100644
> > > --- a/winsup/cygwin/thread.cc
> > > +++ b/winsup/cygwin/thread.cc
> > > @@ -546,6 +546,13 @@ pthread::exit (void *value_ptr)
> > >     class pthread *thread = this;
> > >     _cygtls *tls = cygtls;        /* Save cygtls before deleting this. */
> > > +  /* Deferred cancellation still pending? */
> > > +  if (canceled)
> > > +    {
> > > +      WaitForSingleObject (cancel_event, INFINITE);
> > > +      value_ptr = PTHREAD_CANCELED;
> > > +    }
> > > +
> > >     // run cleanup handlers
> > >     pop_all_cleanup_handlers ();
> > > What do you think?
> > 
> > I mean, by your own interpretation of the standard, this isn't required,
> > because we're allowed to take arbitrarily long to deliver the async
> > cancellation, and in this case, we took so long that the thread exited
> > before it happened, too bad...
> 
> True enough!
> 
> > It doesn't seem a bad addition,
> 
Actually, it seems we actually *have* to do this.  I just searched
for more info on that problem and, to my surprise, I found this in the
most obvious piece of documentation:

https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html

Quote:

  As the meaning of the status is determined by the application (except
  when the thread has been canceled, in which case it is
  PTHREAD_CANCELED), [...]

> On second thought...
> 
> One thing bugging me is this:

This is still a bit fuzzy, though.  I'd appreciate any input.

> Looking into pthread::cancel we have this order of things:
> 
>     // cancel deferred
>     mutex.unlock ();
>     canceled = true;
>     SetEvent (cancel_event);
>     return 0; 
> 
> The canceled var is set before the SetEvent call.
> What if the thread is terminated after canceled is set to true but
> before SetEvent is called?
> 
> pthread::testcancel claims:
> 
>   We check for the canceled flag first. [...]
>   Only if the thread is marked as canceled, we wait for cancel_event
>   being really set, on the off-chance that pthread_cancel gets
>   interrupted before calling SetEvent.
> 
> Neat idea to speed up the code, but doesn't that mean we have a
> potential deadlock, especially given that pthread::testcancel calls WFSO
> with an INFINITE timeout?
> 
> And if so, how do we fix this?  Theoretically, the most simple
> solution might be to call SetEvent before setting the canceled
> variable, but in fact we would have to make setting canceld
> and cancel_event an atomic operation.
> 
> Another idea is never to wait for an INFINITE time.  Logically, if
> canceled is set and cancel_event isn't, the thread just hasn't been
> canceled yet.
> 
> Any better idea?
> 
> > but this turns pthread_exit() into a
> > deferred cancellation point as well, so it should be added to the list of
> > "an implementation may also mark other functions not specified in the
> > standard as cancellation points" in our documentation^W the huge comment in
> > threads.cc.
> 
> Yes, indeed.


Thanks,
Corinna

Reply via email to