[PATCH 0/6] Fix unwinding through sigreturn trampolines

Will Deacon will at kernel.org
Tue Jun 23 09:20:52 EDT 2020

Hi Szabolcs,

Cheers for the reply.

On Tue, Jun 23, 2020 at 12:11:09PM +0100, Szabolcs Nagy wrote:
> as for thread cancellation in glibc: it uses exception
> mechanism for cleanups, but the default cancel state
> is PTHREAD_CANCEL_DEFERRED which means only blocking
> libc calls throw (so -fexceptions is enough and the
> libgcc logic is fine), if you switch to
> PTHREAD_CANCEL_ASYNCHRONOUS then there may be a problem
> but you can only do pure computations in that state,
> (only 3 libc functions are defined to be async cancel
> safe), i think you cannot register cleanup handlers
> that run on the same stack frame that may be async
> interrupted.

Ah, I was trying to print a message, so I suppose that's out. Even so,
debugging with gdb and putting a breakpoint on the callback showed that
it wasn't getting invoked.

My code is below just as an FYI, since being able to derive a test from
this would be useful should we try to fix the CFI directives in future.

I get different results based on different combinations of
architecture, toolchain and optimisation level.



/* cc -O2 -g -o tc tc.c -pthread -fexceptions */

#include <errno.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void cb(void *arg)
	printf("Cleanup handler called %p\n", arg);

int __attribute__((noinline)) baz(volatile int x)
	while (x);
	return x;

void __attribute__((noinline)) bar(volatile int x)
	pthread_cleanup_push(cb, (void *)2);
	x = baz(x);

void *foo(void *unused)
	int otype;

	if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &otype))

	pthread_cleanup_push(cb, (void *)1);
	return NULL;

int main(void)
	pthread_t thread;

	if (pthread_create(&thread, NULL, foo, NULL)) {
		return -1;

	pthread_join(thread, NULL);
	return 0;

More information about the linux-arm-kernel mailing list