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);
>  	}
> 
> > But afaic the stack is always 8 byte aligned anyway.  However, there are
> > some scenarios where 16 byte alignment is required, as for context
> > itself when calling RtlCaptureContext.  Maybe that's the problem here?
> 
> I think so. x86_64 ABI in Windows requires 16 byte alignment.
> https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170
> says:
>     The stack will always be maintained 16-byte aligned, except
>     within the prolog (for example, after the return address is pushed), 
> 
> Therefore, stack alignment here must be 16n +  8 byte alignment.
> Because 'call' instruction pushes the RIP (8 byte) into stack,
> while the code
> context._CX_instPtr = (ULONG_PTR) pthread::static_cancel_self;
> does not do that.
> 
> > But the context Stackptr is the stackpointer of the current function the
> > target thread is running in.  The instruction pointer is set to
> > pthread::static_cancel_self(), which doesn't get any arguments and doesn't
> > use any content from the stack.
> 
> Yeah, that was my question.
> 
> > It might be a good idea to make sure the stack is always 16 byte
> > aligned, but I don't see why pthread::static_cancel_self() ->
> > pthread::cancel_self() -> pthread::exit() would require other than 8
> > byte alignment.
> 
> pthread::exit() calls _cygtls::remove(), and it calls CloseHandle(),
> It appears that, from a certain point, CloseHandle() stopped working
> unless it was 16n + 8 byte aligned.

I confirmed that SbSelectProdedure() does not use 'movaps' instruction
in Windows 10 22H2, while it uses 'movaps' in Win 11 25H2.

On Tue, 16 Dec 2025 13:11:15 +0000
Jon Turney wrote:
> I have the vague idea that this problem started showing up (more?) when 
> the CI VM was upgraded from Windows Server 2022 to Windows Server 2025, 
> but I guess that's maybe just timings...

I guess the same is true between Windows Server 2022 and Windows Server 2025.

> On 14/12/2025 07:39, Takashi Yano via Cygwin wrote:
> >> I'm not sure why this happens, but it also falis in my local environment.
> >> I looked into this issue a bit, and found that access violation happnes
> >> in CloseHandle() in _cygtls::remove().
> >>
> >> And I am also not sure why at all, cancel2 works if CloseHandle()'s are
> >> replaced with NtClose() as follows.
> 
> I think this is just the difference between the two calls: CloseHandle 
> generates an exception whereas NtClose returns an error code if the 
> handle is invalid.

Perhaps, NtClose() does not use SbSelectProcedure(), then it works
on 8 byte alignment by chance.

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