// Check that if LSan finds that SP doesn't point into thread stack (e.g. // if swapcontext is used), LSan will not hit the guard page. // RUN: %clang_lsan %s -o %t && %run %t #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <ucontext.h> pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int ctxfunc_started = 0; static void die(const char* msg, int err) { if (err == 0) err = errno; fprintf(stderr, "%s: %s\n", msg, strerror(err)); exit(EXIT_FAILURE); } static void ctxfunc() { pthread_mutex_lock(&mutex); ctxfunc_started = 1; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); // Leave this context alive when the program exits. for (;;); } static void* thread(void* arg) { (void)arg; ucontext_t ctx; void* stack; if (getcontext(&ctx) < 0) die("getcontext", 0); stack = malloc(1 << 10); if (stack == NULL) die("malloc", 0); ctx.uc_stack.ss_sp = stack; ctx.uc_stack.ss_size = 1 << 10; makecontext(&ctx, ctxfunc, 0); setcontext(&ctx); die("setcontext", 0); return NULL; } int main() { pthread_t tid; int i; pthread_mutex_lock(&mutex); i = pthread_create(&tid, NULL, thread, NULL); if (i != 0) die("pthread_create", i); while (!ctxfunc_started) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); return 0; }