... единственное, что я мог думать, что достаточно привести бы ключ, чтобы изменить значение
Наиболее вероятные причины pthread_getspecific
вернуться NULL
:
- вы в факт, выполняющийся в новом потоке, в котором
pthread_setspecific
не был вызван,
- вы вызываете
pthread_getspecific
, а текущий поток находится в процессе уничтожается (т. pthread_exit
находится где-то в стеке),
- вы вызываете
pthread_getspecific
в обработчик сигнала (ни одна из функций pthread_*
не является безопасным асинхронным сигналом).
Предполагая, что ни одна из приведенных выше причин не верна в вашем случае, на выставке.
Для начала нам нужен тестовый пример.
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_key_t key;
void *thrfn(void *p) {
int rc = pthread_setspecific(key, &p);
assert(rc == 0);
sleep(60);
rc = pthread_setspecific(key, (void*)0x112233);
assert(rc == 0);
return p;
}
int main()
{
pthread_t thr;
int rc = pthread_key_create(&key, NULL);
assert(rc == 0);
rc = pthread_create(&thr, NULL, thrfn, NULL);
assert(rc == 0);
sleep(90);
return 0;
}
gcc -g -pthread t.c
gdb -q ./a.out
(gdb) start
Теперь это очень помогает иметь GLIBC, который скомпилирован с информацией об отладке. Большинство дистрибутивов предоставляют libc-dbg
или аналогичный пакет, который обеспечивает это. Посмотрев на pthread_setspecific source, вы можете видеть, что внутри дескриптора потока (self
) есть массив specific_1stblock
, где пространство для первого PTHREAD_KEY_2NDLEVEL_SIZE
== 32 ключевых слота предварительно выделено (32 отдельных ключа обычно более чем достаточно).
Значение, которое мы передаем, будет храниться в self->specific_1stblock[key].data
, и это именно то место, где вы хотите установить точку наблюдения.
В нашей примерной программе key == 0
(так как это самый первый ключ). Собираем все вместе:
Starting program: /tmp/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Temporary breakpoint 1, main() at t.c:21
21 int rc = pthread_key_create(&key, NULL);
(gdb) b pthread_setspecific
Breakpoint 2 at 0x7ffff7bc9460: file pthread_setspecific.c, line 28.
(gdb) c
Continuing.
[New Thread 0x7ffff77f6700 (LWP 58683)]
[Switching to Thread 0x7ffff77f6700 (LWP 58683)]
Breakpoint 2, __GI___pthread_setspecific (key=0, value=0x7ffff77f5ef8) at pthread_setspecific.c:28
28 pthread_setspecific.c: No such file or directory.
(gdb) n
35 in pthread_setspecific.c
(gdb) n
28 in pthread_setspecific.c
(gdb) p self
$1 = (struct pthread *) 0x7ffff77f6700
(gdb) watch -l self.specific_1stblock[key].data
Hardware watchpoint 3: -location self.specific_1stblock[key].data
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x0
New value = (void *) 0x7ffff77f5ef8
__GI___pthread_setspecific (key=<optimized out>, value=0x7ffff77f5ef8) at pthread_setspecific.c:89
89 in pthread_setspecific.c
Обратите внимание, что новое значение точно значение, которое мы перешли к pthread_setspecific
.
(gdb) c
Continuing.
Breakpoint 2, __GI___pthread_setspecific (key=0, value=0x112233) at pthread_setspecific.c:28
28 in pthread_setspecific.c
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x7ffff77f5ef8
New value = (void *) 0x112233
__GI___pthread_setspecific (key=<optimized out>, value=0x112233) at pthread_setspecific.c:89
89 in pthread_setspecific.c
Это наш второй pthread_setspecific
вызов
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x112233
New value = (void *) 0x0
__nptl_deallocate_tsd() at pthread_create.c:152
152 pthread_create.c: No such file or directory.
И это разрушение нить, которая освобождает сам дескриптор потока.
(gdb) c
Continuing.
[Thread 0x7ffff77f6700 (LWP 58683) exited]
[Inferior 1 (process 58677) exited normally]
Да, это возможно. Точные детали зависят от платформы, хотя вы сохранили тайну. Это Linux/x86_64/GLIBC или что-то еще? –
Я действительно, и я отредактировал вопрос, чтобы включить это. Благодаря! –