|
3 | 3 | // license that can be found in the LICENSE file. |
4 | 4 |
|
5 | 5 | #include <pthread.h> |
| 6 | +#include <errno.h> |
6 | 7 | #include <string.h> |
7 | 8 | #include <signal.h> |
| 9 | +#include <stdlib.h> |
8 | 10 | #include "libcgo.h" |
9 | 11 | #include "libcgo_unix.h" |
10 | 12 |
|
@@ -59,14 +61,34 @@ threadentry(void *v) |
59 | 61 | void |
60 | 62 | x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) |
61 | 63 | { |
62 | | - pthread_attr_t attr; |
| 64 | + pthread_attr_t *attr; |
63 | 65 | size_t size; |
64 | 66 |
|
| 67 | + /* The memory sanitizer distributed with versions of clang |
| 68 | + before 3.8 has a bug: if you call mmap before malloc, mmap |
| 69 | + may return an address that is later overwritten by the msan |
| 70 | + library. Avoid this problem by forcing a call to malloc |
| 71 | + here, before we ever call malloc. |
| 72 | +
|
| 73 | + This is only required for the memory sanitizer, so it's |
| 74 | + unfortunate that we always run it. It should be possible |
| 75 | + to remove this when we no longer care about versions of |
| 76 | + clang before 3.8. The test for this is |
| 77 | + misc/cgo/testsanitizers. |
| 78 | +
|
| 79 | + GCC works hard to eliminate a seemingly unnecessary call to |
| 80 | + malloc, so we actually use the memory we allocate. */ |
| 81 | + |
65 | 82 | setg_gcc = setg; |
66 | | - pthread_attr_init(&attr); |
67 | | - pthread_attr_getstacksize(&attr, &size); |
68 | | - g->stacklo = (uintptr)&attr - size + 4096; |
69 | | - pthread_attr_destroy(&attr); |
| 83 | + attr = (pthread_attr_t*)malloc(sizeof *attr); |
| 84 | + if (attr == NULL) { |
| 85 | + fatalf("malloc failed: %s", strerror(errno)); |
| 86 | + } |
| 87 | + pthread_attr_init(attr); |
| 88 | + pthread_attr_getstacksize(attr, &size); |
| 89 | + g->stacklo = (uintptr)&size - size + 4096; |
| 90 | + pthread_attr_destroy(attr); |
| 91 | + free(attr); |
70 | 92 |
|
71 | 93 | if (x_cgo_inittls) { |
72 | 94 | x_cgo_inittls(tlsg, tlsbase); |
|
0 commit comments