Re: Recent testsuite/winsup.api/pthread/cancel2 failure

Takashi Yano via Cygwin <[email protected]>
Newsgroups gmane.os.cygwin
Message-ID <[email protected]>
On Tue, 23 Dec 2025 19:07:13 +0900
Takashi Yano wrote:
> On Mon, 22 Dec 2025 16:46:53 +0100
> Corinna Vinschen wrote:
> > On Dec 22 23:37, Takashi Yano via Cygwin wrote:
> > > Alignment issue?
> > > 
> > > This might be the right thing.
> > > 
> > > diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
> > > index 86a00e76e..ec1e3c98c 100644
> > > --- a/winsup/cygwin/thread.cc
> > > +++ b/winsup/cygwin/thread.cc
> > > @@ -630,6 +630,8 @@ pthread::cancel ()
> > >        threadlist_t *tl_entry = cygheap->find_tls (cygtls);
> > >        if (!cygtls->inside_kernel (&context))
> > >  	{
> > > +	  if ((context._CX_stackPtr & 8) == 0)
> > > +	    context._CX_stackPtr -= 8;
> > 
> > Does that really help?  Checking for 8 byte alignment is usually done
> > with (X & 7) != 0, because this won't catch 16 byte aligned stacks.
> 
> This code does not aim for 8 byte alignment, but 16n + 8. I assume
> context._CX_stackPtr & 7 is always 0. I wonder if this assumption
> is true. What if user code pushes 16 bit register such as AX?
> It might be necessary to mask least 3 bits in advance.
> 
> diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
> index 86a00e76e..628aef16f 100644
> --- a/winsup/cygwin/thread.cc
> +++ b/winsup/cygwin/thread.cc
> @@ -630,6 +630,9 @@ pthread::cancel ()
>        threadlist_t *tl_entry = cygheap->find_tls (cygtls);
>        if (!cygtls->inside_kernel (&context))
>  	{
> +	  context._CX_stackPtr &= 0xfffffffffffffff8UL;
> +	  if ((context._CX_stackPtr & 8) == 0)
> +	    context._CX_stackPtr -= 8;
>  	  context._CX_instPtr = (ULONG_PTR) pthread::static_cancel_self;
>  	  SetThreadContext (win32_obj_id, &context);
>  	}

I confirmed that the attached reproducer (repro.c) works fine with
this patch.

-- 
Takashi Yano <[email protected]>


-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple
repro.c (text/x-csrc, 995 B)
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

#define USE_ASYNC 1
static int thread_started;

void *mythread(void *)
{
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
#if USE_ASYNC
  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#else
  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
#endif

  thread_started = 1;

  for (;;)
    {	  
      __asm__ ("push %ax");
      for (volatile int i=0; i<1000; i++) ;
      __asm__ ("pop %ax");
      for (volatile int i=0; i<1000; i++) ;
#if !USE_ASYNC
      pthread_testcancel();
#endif
    }

  return NULL;
}

int main()
{
  int i;
  pthread_t t;
  void *result = 0;

  thread_started = 0;
  pthread_create(&t, NULL, mythread, NULL);

  while (thread_started == 0)
    usleep(1000);

  usleep(10000);
  pthread_cancel(t);

  pthread_join(t, &result);
  if (result != PTHREAD_CANCELED)
    printf("Thread started %d: result %d\n", thread_started, result);
  else
    printf("Thread canceled.\n");

  return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.