1ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany// Regression test for a leak in tsd:
2ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany// https://code.google.com/p/address-sanitizer/issues/detail?id=233
35d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// RUN: %clangxx_asan -O1 %s -pthread -o %t
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// RUN: ASAN_OPTIONS=quarantine_size=1 %run %t
5ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany#include <pthread.h>
6ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany#include <stdio.h>
7ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany#include <stdlib.h>
8ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany#include <assert.h>
95d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include <sanitizer/allocator_interface.h>
10ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany
11ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryanystatic pthread_key_t tsd_key;
12ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany
13ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryanyvoid *Thread(void *) {
14ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  pthread_setspecific(tsd_key, malloc(10));
15ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  return 0;
16ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany}
17ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany
18ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryanystatic volatile void *v;
19ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany
20ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryanyvoid Dtor(void *tsd) {
21ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  v = malloc(10000);
22ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  free(tsd);
23ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  free((void*)v);  // The bug was that this was leaking.
24ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany}
25ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany
26ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryanyint main() {
27ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  assert(0 == pthread_key_create(&tsd_key, Dtor));
28ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  size_t old_heap_size = 0;
29ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  for (int i = 0; i < 10; i++) {
30ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    pthread_t t;
31ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    pthread_create(&t, 0, Thread, 0);
32ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    pthread_join(t, 0);
335d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    size_t new_heap_size = __sanitizer_get_heap_size();
34ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, old_heap_size);
35ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    if (old_heap_size)
36ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany      assert(old_heap_size == new_heap_size);
37ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany    old_heap_size = new_heap_size;
38ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  }
39ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany}
40